Czy GNU Grep może generować wybraną grupę?

47

Czy można użyć GNU grep, aby uzyskać dopasowaną grupę z wyrażenia?

Przykład:

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

Który wyprowadziłby „słupek”. Ale chciałbym dostać tylko „pasek”, bez konieczności wysyłania go jeszcze raz przez grep (tj. Pobierz dopasowaną grupę). Czy to jest możliwe?

Torandi
źródło

Odpowiedzi:

50

Możesz seddo tego użyć . Na BSD sed:

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

Lub bez -Eopcji:

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

To nie działa w przypadku wprowadzania wielowierszowego. Do tego potrzebujesz:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
źródło
Dzięki, zapomniałem o sed. Ale dla wyjaśnienia sed nie przyjmuje argumentu -E ..
Torandi
Hm, działa na moim komputerze (Mac OS X). Po dalszym zbadaniu na stronie podręcznika: „Opcje -E, -a i -i są niestandardowymi rozszerzeniami FreeBSD i mogą nie być dostępne w innych systemach operacyjnych.”
jtbandes
1
-r wydaje mi się, że tak.
Torandi
1
@jtbandes: Nie potrzebujesz rozszerzonych funkcji dla tego wyrażenia. Potrzebuję tylko 3 znaków zmiany znaczenia do ( ) +użycia \( \) \+: To jest właściwie to samo:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O
2
To nie działa w przypadku wprowadzania wielowierszowego. Do tego potrzebujesz: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead,
28

Chociaż grep nie może wypisać konkretnej grupy, możesz użyć funkcji lookahead i asercji, aby osiągnąć to, czego potrzebujesz:

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

Aldrik
źródło
8
grep -Pnie jest dostępny na wszystkich platformach. Ale jeśli tak jest, użycie lookahead / behind jest bardzo dobrym sposobem na rozwiązanie problemu.
Sébastien
1
Czy grep jest inteligentny dzięki twierdzeniom, które się spóźniają? Jak to działa z długimi opóźnieniami? Czy integruje przeszłość z jakimś „drzewem sufiksów” z resztą wyrażenia regularnego?
Ross Rogers
3

Możesz użyć, \Kaby zresetować i odrzucić tekst dopasowania po lewej stronie wraz z lookahead, który nie jest dodawany do tekstu dopasowania:

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

Tylko GNU grep.

Drawk
źródło