Правильное регулярное выражение не работает в grep

Ваша команда sed отправляет результат только на стандартный вывод. Вам придется перенаправить его в последующей команде (НЕ в той же самой команде, например sed 'sedcommand' file > file, так как это приведет к стиранию файла до его обработки).

Вы также можете передать команды в ed вместо использования sed :

for file in $filelist ; do
  echo -e '%s/yyyymmdd/YYYYMMDDHH24MISS/g\nw' | ed $file
done

который заменяет в каждой строке (%), а затем, после разделительной новой строки (\n), записывает измененный файл на место (w).

12
11.02.2019, 11:42
3 ответа

Кажется, вы определили правильное регулярное выражение, но не установили достаточные флаги в строке команды -, чтобы grepего понял. Потому что по умолчанию grepподдерживает BRE, а с флагом -E— ERE. То, что у вас есть (смотреть -вперед )доступно только в варианте регулярного выражения PCRE, который поддерживается только в GNU grepс его флагом -P.

Предполагая, что вам нужно извлечь только совпадающую строку после prefix, вам нужно добавить дополнительный флаг -o, чтобы сообщить grep, что печатается только совпадающая часть как

grep -oP '(?<=prefix).*$' <<< prefixSTRING

Существует также версия grep, которая по умолчанию поддерживает библиотеки PCRE -pcregrep, в которой вы можете просто выполнить

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

Подробное объяснение различных разновидностей регулярных выражений дано в этом замечательном ответе Джайлса и инструментах, реализующих каждый из них

42
27.01.2020, 19:54

Регулярные выражения бывают разных видов. Вы показываете Perl -как регулярное выражение (PCRE, "Perl Compatible Regular Expression" ).

grepиспользует регулярные выражения POSIX. Это базовые регулярные выражения(BRE )и расширенные регулярные выражения(ERE, если grepиспользуется с опцией -E). См. руководство для re_formatили regexили любое другое подобное руководство, на которое ссылается ваше руководство grepв вашей системе, или стандартные тексты POSIX, на которые я только что ссылался.

Если вы используете GNU grep, вы сможете использовать Perl -как регулярные выражения, если вы использовали grepс опцией -P, специфичной для GNU grep-.

Также обратите внимание, что grepпо умолчанию возвращает строк , а не подстроки из строк. Опять же, с GNUgrep(и некоторыми другими реализациями grep)вы можете использовать опцию -o, чтобы получить только бит (s ), который соответствует заданному выражению из каждой строки.

Обратите внимание, что -Pи -oне являются -стандартными расширениями спецификации POSIXgrep.

Если вы не используете GNU grep, вы можете вместо этого использовать sed, чтобы получить бит между строкой prefixи концом строки:

sed -n 's/.*prefix\(.*\)/\1/p' file

При этом печатаются только те строки, к которым sedудается применить данную замену. Подстановка заменит всю строку, соответствующую выражению (, являющемуся BRE ), на ее часть, расположенную после строки prefix.

Обратите внимание, что если в строке есть несколько экземпляров prefix, вариант sedвернет строку после последнего , а вариант GNU grepвернет строку после первый один (, который будет включать другие экземплярыprefix).

Решение sedбудет переносимым на все Unix -подобные системы.

38
27.01.2020, 19:54

Как указывалось в других ответах, grepне использует вариант регулярного выражения с просмотром назад (по умолчанию в GNU grepили вообще не использует его в других версиях ).

Если вы не можете использовать GNU grepили pcregrep, вы можете использовать perl, если он у вас есть.

Командная строка эквивалентна perl::

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

Вы помещаете нужное регулярное выражение между косой чертой. Поскольку вы используете Perl, здесь используется разновидность регулярных выражений Perl .

6
27.01.2020, 19:54

Теги

Похожие вопросы