Выделение метасимволов в основных / расширенных строках регулярных выражений posix в grep

Можно ли избежать всех метасимволов строки внутри переменной, прежде чем передавать ее в grep? Я знаю, что подобный вопрос был задан раньше на SE ( здесь ), а также хорошее объяснение здесь , но мне было просто интересно, возможно ли это с базовым / расширенным шаблоном regex posix вместо perl-шаблона? (в настоящее время я читаю синтаксис regex perl, чтобы понять его сначала, а не прыгать в решение)

Почему это требование: (Мета, не требуется для ответа)

Я пытался написать небольшой скрипт для разделения больших файлов, где я разделял файлы на file_name.ext.000 , file_name.ext.001 … и т. Д., file_name.ext.001 отлично работает. Теперь мне не нравится разделять те файлы, которые уже разделены (т. Е. Имеют имена файлов с 3-мя символьными расширениями, которые являются всеми цифрами, а их размер суммируется до исходного размера файла. Теперь, если я использую простое расширение оболочки, например file_name.ext.* он также соответствует файлам, имеющим file_name.ext.ext2 и, следовательно, общие несоответствия размера и разделение происходит, даже если нет необходимости повторно отбирать. Поэтому я бы проверял только файлы, имеющие имя file_name.ext.### where ### являются цифрами. Мое текущее выражение, чтобы найти размер файла этих частей, выглядит следующим образом:

 FILE_SIZE_EXISTING=$( (find "$DESTINATION" -type f -regextype posix-extended -regex "^$DESTINATION/$FILE_BASENAME(\.[[:digit:]]{3})?$" -print0 | xargs -0 stat --printf="%s\\n" 2>/dev/null || echo 0) | paste -sd+ | bc) 

Это работает для простых имен файлов. Однако это не работает, если какое-то причудливое имя, например, содержит [] и т. Д. Существует ли обходной путь? Я новичок в сценариях оболочки и, следовательно, не знаю perl.

One Solution collect form web for “Выделение метасимволов в основных / расширенных строках регулярных выражений posix в grep”

Как процитировать специальные символы (переносимо)

Следующий фрагмент добавляет обратную косую черту перед каждым символом, который является особым в расширенных регулярных выражениях, используя sed чтобы заменить любое появление одного из символов ][()\.^$?*+ Обратным слэшем, за которым следует этот символ:

 raw_string='test[string]\.wibble' quoted_string=$(printf %s "$raw_string" | sed 's/[][()\.^$?*+]/\\&/g') 

Это приведет к удалению конечных строк в $raw_string ; если это проблема, убедитесь, что строка не заканчивается символом новой строки, добавив инертный символ в конце, а затем удалите этот символ.

 quoted_string=$(printf %sa "$raw_string" | sed 's/[][()\.^$?*+]/\\&/g') quoted_string=${quoted_string%?} 

Как цитировать специальные символы (в bash или zsh)

Bash и zsh имеют функцию замены шаблона, которая может быть быстрее, если строка не очень длинная. Это громоздко здесь, потому что замена должна быть строкой, поэтому каждый символ нужно заменять отдельно. Обратите внимание, что сначала вы должны избегать обратных косых черт.

 quoted_string=${raw_string//\\//\\\\} for c in \[ \] \( \) \. \^ \$ \? \* \+; do quoted_string=${quoted_string//"$c"/"\\$c"} done 

Как цитировать специальные символы (в ksh93)

Конструкция замены струн Ksh более мощная, чем уполированная версия в bash и zsh. Он поддерживает ссылки на группы в шаблоне.

 quoted_string=${raw_string//@([][()\.^$?*+])/\\\1} 

Что вы на самом деле хотите

Вам не нужно find здесь: шаблонов оболочки достаточно для соответствия файлам, заканчивающимся тремя цифрами. Если файл детали не существует, шаблон шара остается нерасширенным. Существует также более простой способ добавления размеров файлов: вместо использования stat (который существует во многих вариантах unix, но имеет различный синтаксис для каждого) и выполняет сложную конвейерную обработку для суммирования значений, вы можете вызвать wc -c (на обычные файлы, на большинстве систем wc будет смотреть на размер файла и не беспокоить, чтобы открыть файл и прочитать байты).

 set -- "$DESTINATION/$FILE_BASENAME".[0-9][0-9][0-9] case $1 in *\]) # The glob was left intact, so no part exists do_split …;; *) # The glob was expanded, so at least one part exists FILE_SIZE_EXISTING=$(wc -c "$@" | sed -n '$s/[^0-9]//gp') if [ "$FILE_SIZE_EXISTING" -ne "$(wc -c <"$DESTINATION/$FILE_BASENAME")" ]; then do_split … fi 

Обратите внимание, что ваш тест на общий размер не очень надежный: если файл изменился, но остался одного и того же размера, вы получите устаревшие детали. Это нормально, если файлы никогда не меняются, и единственный риск состоит в том, что части могут быть усечены или отсутствуют.

  • Усечь третий столбец до тех пор, пока не будут указаны строки
  • Perl не-жадное регулярное выражение больше, чем должно
  • Поиск максимального значения в файле
  • Двухфакторная аутентификация SFTP
  • Замена текста из списка замен. Добавлено осложнение: обратная косая черта
  • Переформатирование документа LaTeX по perl
  • Извлечение данных из файлов в нескольких каталогах
  • sed / awk / perl - удаление пробелов между двумя строками / словами + solaris 10
  • Команда UNIX для замены в разделителе в зависимости от положения разделителя
  • Как преобразовать <a href="http://xy.com"> XY </a> в ?
  • вход perl-get, условия проверки
  • Проверка окончаний строки из текста, созданного perl-скриптом
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.