Kann GNU Grep eine ausgewählte Gruppe ausgeben?

47

Ist es möglich, GNU grep zu verwenden, um eine übereinstimmende Gruppe aus einem Ausdruck zu erhalten?

Beispiel:

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

Welches würde "'bar'" ausgeben. Aber ich möchte nur "bar" bekommen, ohne es noch einmal durch grep senden zu müssen (dh die passende Gruppe bekommen). Ist das möglich?

Torandi
quelle

Antworten:

50

Sie können dafür verwenden sed. Auf BSD sed:

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

Oder ohne die -EOption:

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

Dies funktioniert bei mehrzeiligen Eingaben nicht. Dafür brauchst du:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
quelle
Danke, hatte sed vergessen. Aber zur Klarstellung nimmt sed nicht das Argument -E ..
Torandi
Hm, das funktioniert auf meinem Computer (Mac OS X). Weitere Informationen finden Sie auf der Manpage unter: "Die Optionen -E, -a und -i sind nicht standardmäßige FreeBSD-Erweiterungen und stehen unter anderen Betriebssystemen möglicherweise nicht zur Verfügung."
jtbandes
1
-r scheint mir das zu sein.
Torandi
1
@jtbandes: Sie haben nicht die erweiterten Funktionen für diesen Ausdruck brauchen .. Ich muss nur 3 Escape - Zeichen für den ( ) +Einsatz \( \) \+: Dies ist effektiv gleich:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O
2
Dies funktioniert bei mehrzeiligen Eingaben nicht. Dafür benötigen Sie: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead
28

Grep kann zwar keine bestimmte Gruppe ausgeben, Sie können jedoch Lookahead- und Behind-Assertions verwenden, um das zu erreichen, wonach Sie suchen:

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

Aldrik
quelle
8
grep -Pist nicht auf allen Plattformen verfügbar. Aber wenn ja, ist die Verwendung von Lookahead / Behind eine sehr gute Möglichkeit, das Problem zu lösen.
Sébastien,
1
Ist grep intelligent bei den Look-Behind-Behauptungen? Wie funktioniert es mit langen Blickhintergründen? Integriert es die Look-Behinds in eine Art "Suffix-Baum" mit dem Rest des Regex?
Ross Rogers
3

Sie können \Kden linken Match-Text zusammen mit einem Lookahead, der nicht zum Match-Text hinzugefügt wird, zurücksetzen und verwerfen:

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

Nur GNU grep.

zeichnete
quelle