użycie naprzemiennej „|” w wyrażeniu regularnym sed

78

Używam sed, GNU sed wersja 4.2.1. Chcę użyć alternatywy „|” symbol w podwyrażeniu. Na przykład :

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

powinien wrócić

" blib bou "

ale powraca

"blia blib bou blf".

Jak mogę uzyskać oczekiwany wynik?

Cedric
źródło

Odpowiedzi:

110

„|” potrzebuje także odwrotnego ukośnika, aby uzyskać jego specjalne znaczenie.

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

zrobi co chcesz.

Jak wiesz, jeśli wszystko inne zawiedzie, przeczytaj instrukcję :-).

Podręcznik użytkownika GNU sed , sekcja 3.3 Przegląd składni wyrażeń regularnych :

`REGEXP1 \ | REGEXP2 '

Odpowiada REGEXP1 lub REGEXP2.

Zwróć uwagę na odwrotny ukośnik ...

Niestety składnia wyrażeń regularnych nie jest tak naprawdę ustandaryzowana ... istnieje wiele wariantów, które różnią się między innymi tym, w których „znakach specjalnych” potrzeba \ a które nie. W niektórych jest nawet konfigurowalny lub zależy od przełączników (jak w GNU grep, które można przełączać między trzema różnymi dialektami wyrażeń regularnych).

Ta odpowiedź dotyczy w szczególności GNU sed . Istnieją inne sedwarianty, na przykład ten stosowany w BSD, które zachowują się inaczej.

Śleske
źródło
35
Dla kogokolwiek innego mylonego tą odpowiedzią \ | działa tylko w gnu sed (gsed na os x), a nie waniliowy sed (sed na os x).
Andrew Hancox
@AndrewHancox Dziękuję bardzo! Już miałam oderwać wszystkie włosy z głowy (do tej pory radzę sobie całkiem nieźle w porównaniu do mojego menedżera z przodu włosów) - wiem, że znam RegEx wystarczająco dużo, aby spróbować | i \ | ale nigdy nie myślałem o tym, że OSX może faktycznie używać nie-GNU sed.
phatskat
8
Standardowa wersja BSD / OS X sedobsługuje naprzemiennie, ale tylko z „rozszerzoną” składnią wyrażenia regularnego ( -E) - co oznacza, że ​​nie ma ukośników odwrotnych ani w potokach, ani w nawiasach:echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
Mark Reed
2
Zredagowałem swoją odpowiedź, aby zauważyć, że dotyczy tylko GNU sed.
sleske,
22

Ponieważ istnieje kilka komentarzy dotyczących sedimplementacji innych niż Gnu : Przynajmniej w OS X, możesz użyć -Eargumentu, aby  sed:

Interpretuj wyrażenia regularne jako rozszerzone (nowoczesne) wyrażenia regularne zamiast podstawowych wyrażeń regularnych (BRE). Strona podręcznika re_format (7) w pełni opisuje oba formaty.

Następnie możesz używać metaznaków wyrażeń regularnych bez ich ucieczki. Przykład:

$ echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
 blib bou 
Daniel Beck
źródło
12

GNU sed obsługuje również tę -ropcję (rozszerzone wyrażenia regularne). Oznacza to, że nie musisz uciekać przed metaznakami:

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

Wynik:

hi hi
jco
źródło
Tak, -ropcja jest naprawdę bardzo pomocna dla czytelności wyrażeń. To powinna być zaakceptowana odpowiedź.
рüффп
9

To \|również nie działa z sed na Solarisie 10. Zrobiłem to

perl -p -e 's/bl(ia|f)//g'
Joe Tennies
źródło
2
+1 za przenośność, ponieważ jeśli system ma perla, zawsze użyje tej składni, w przeciwieństwie do sed.
evilsoup
4

Kontynuacja: sed -E zezwala na to w systemie MacOS. Nie ma potrzeby stosowania odwrotnego ukośnika.

 sed -E 's/this|orthat/oooo/g' infile
jakieś pomysły
źródło
1

W GnuWin32 na Windows sed składnia jest następująca sed "s/thing1\|thing2/ /g" source > destination.

Cytaty muszą być typu "- jest to „Wymagane”, aby polecenie zostało przeanalizowane.

twobob
źródło