использование чередования «|» в регулярном выражении sed

79

Я использую sed, GNU sed версия 4.2.1. Я хочу использовать чередование "|" символ в подвыражении. Например :

echo "blia blib bou blf" | sed 's/bl\(ia|f\)//g'

должен вернуться

" blib bou "

но возвращается

"blia blib bou blf".

Как я могу получить ожидаемый результат?

Седрик
источник

Ответы:

110

"|" также нужен обратный слеш, чтобы получить его особое значение.

echo "blia blib bou blf" | sed 's/bl\(ia\|f\)//g'

будет делать то, что вы хотите.

Как вы знаете, если ничего не помогает, прочитайте руководство :-).

Руководство пользователя GNU sed , раздел 3.3 Обзор синтаксиса регулярных выражений :

`REGEXP1 \ | REGEXP2'

Совпадает с REGEXP1 или REGEXP2.

Обратите внимание на обратную косую черту ...

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

Этот ответ, в частности, для GNU sed . Есть и другие sedварианты, например, тот, который используется в BSD, которые ведут себя по-разному.

sleske
источник
35
Для всех, кто смущен этим ответом \ | работает только в gnu sed (gsed на os x), а не ванильный sed (sed на os x).
Эндрю Хэнкокс
@AndrewHancox Спасибо большое! Я собирался вырвать все волосы из моей головы (и пока у меня все хорошо, по сравнению с моим менеджером по волосам) - я знаю, что знаю RegEx достаточно, чтобы попробовать | и \ | но я никогда не думал о том, что OSX может использовать не-GNU-sed.
phatskat
8
Стандартная версия BSD / OS X sedподдерживает чередование, но только с «расширенным» синтаксисом регулярных выражений ( -E) - что означает отсутствие обратной косой черты ни в каналах, ни в скобках:echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
Марк Рид
2
Я отредактировал свой ответ, чтобы отметить, что это только для GNU sed.
слеське
23

Поскольку есть несколько комментариев относительно реализаций не-Gnu sed: По крайней мере, в OS X вы можете использовать -Eаргумент для  sed:

Регулярные выражения интерпретировать как расширенные (современные) регулярные выражения, а не как базовые регулярные выражения (BRE). Страница справочника re_format (7) полностью описывает оба формата.

Затем вы можете использовать метасимволы регулярных выражений, не экранируя их. Пример:

$ echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
 blib bou 
Даниэль Бек
источник
12

GNU sed также поддерживает эту -rопцию (расширенные регулярные выражения). Это означает, что вам не нужно избегать метасимволов:

echo foohello barhello | sed -re "s/(foo|bar)hello/hi/g"

Выход:

hi hi
объединенная комиссия по океанографии
источник
Да, -rопция действительно очень полезна для удобства чтения выражений. Это должен быть принятый ответ.
рüффп
9

Также \|не работает с sed на Solaris 10. То, что я сделал, было использовать

perl -p -e 's/bl(ia|f)//g'
Джо Теннис
источник
2
+1 для переносимости, так как, если система имеет Perl, она всегда будет использовать этот синтаксис, в отличие от sed.
evilsoup
4

Продолжение: sed -E позволяет это на MacOS. Никакой обратной косой черты не требуется для |.

 sed -E 's/this|orthat/oooo/g' infile
некоторые идеи
источник
1

В GnuWin32 на Windows sed синтаксис такой sed "s/thing1\|thing2/ /g" source > destination.

Кавычки должны иметь тип "- это «Обязательно» для разбора команды.

twobob
источник