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

57242
Torandi

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

Пример:

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

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

42

3 ответа на вопрос

47
jtbandes

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

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

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

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

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

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

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

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

`grep -P` доступен не на всех платформах. Но если это так, использование lookahead / behind - очень хороший способ решения проблемы. Sébastien 11 лет назад 6
Действительно ли grep интеллектуален с утверждениями о заглядывании? Как это работает с длинными оглядками? Интегрирует ли он в какое-то [[суффиксное дерево]] (http://en.wikipedia.org/wiki/Suffix_tree) с остальной частью регулярного выражения? Ross Rogers 11 лет назад 1
2
drewk

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

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

GNU grep only.

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