Может ли GNU Grep выводить выбранную группу?

48

Можно ли использовать GNU grep для получения подходящей группы из выражения?

Пример:

echo "foo 'bar'" | grep -oE "'([^']+)'"

Который вывел бы "бар". Но я хотел бы получить просто «бар», без необходимости отправлять его через grep еще раз (т.е. получить соответствующую группу). Это возможно?

Torandi
источник

Ответы:

50

Вы можете использовать sedдля этого. На BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

Или без -Eопции:

sed "s/.*'\([^']\+\)'.*/\1/"

Это не работает для многострочного ввода. Для этого вам нужно:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
источник
1
Хм, это на моей машине (Mac OS X). При дальнейшем рассмотрении на странице руководства: «Опции -E, -a и -i являются нестандартными расширениями FreeBSD и могут быть недоступны в других операционных системах».
jtbandes
1
Это похоже на grep'-E: «Регулярные выражения интерпретируются как расширенные (современные) регулярные выражения, а не как базовые регулярные выражения (BRE). Страница справочника re_format (7) полностью описывает оба формата».
Jtbandes
1
-R кажется, что для меня.
Торанди
1
@jtbandes: Вам не нужны расширенные функции для этого выражения. Мне просто нужны 3 экранирующих символа для ( ) +использования \( \) \+: это фактически то же самое:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O
2
Это не работает для многострочного ввода. Для этого вам нужно: sed -n "s/.*'\([^']\+\)'.*/\1/p"
подонок
28

Хотя grep не может вывести конкретную группу, вы можете использовать прогнозирование и утверждения позади, чтобы добиться того, что вы после:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"

Aldrik
источник
8
grep -Pдоступно не на всех платформах. Но если это так, использование lookahead / behind - очень хороший способ решения проблемы.
Себастьян
1
Является ли grep интеллектуальным с утверждениями о поиске? Как это работает с длинными оглядками? Интегрирует ли он в какое-то «дерево суффиксов» с остальной частью регулярного выражения?
Росс Роджерс
4

Вы можете использовать \Kдля сброса и отбрасывания текста совпадения левой руки вместе с предвкушением, которое не добавляется в текст совпадения:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

GNU grep only.

drewk
источник