Kann GNU Grep eine ausgewählte Gruppe ausgeben?

57807
Torandi

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. Ich würde aber gerne nur "bar" bekommen, ohne es noch einmal durch grep schicken zu müssen (dh die passende Gruppe zu bekommen). Ist das möglich?

42

3 Antworten auf die Frage

47
jtbandes

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 nicht bei mehrzeiliger Eingabe. Dafür brauchen Sie:

sed -n "s/.*'\([^']\+\)'.*/\1/p" 
Danke, hatte Sed vergessen. Aber um zu klären, nimmt sed nicht das Argument -E. Torandi vor 15 Jahren 0
Hm, das geht auf meinem Rechner (Mac OS X). Nach weiterer Prüfung in der Manpage: "Die Optionen -E, -a und -i sind nicht standardmäßige FreeBSD-Erweiterungen und möglicherweise nicht auf anderen Betriebssystemen verfügbar." jtbandes vor 15 Jahren 0
Okay, nicht bei mir (debian), was soll -E tun? Torandi vor 15 Jahren 0
Es ist ähnlich wie bei 'grep` -E: "Interpretiere reguläre Ausdrücke als erweiterte (moderne) reguläre Ausdrücke und nicht als reguläre reguläre Ausdrücke (BREs). Die re_format (7) -Manpage beschreibt beide Formate vollständig." jtbandes vor 15 Jahren 0
-r scheint mir das zu sein. Torandi vor 15 Jahren 1
Und ich habe -r nicht. Naja! jtbandes vor 15 Jahren 0
@jtbandes: Sie benötigen die erweiterten Funktionen für diesen Ausdruck nicht. Ich benötige nur 3 Escape-Zeichen für `() +` verwende `\ (\) \ +`: Dies ist im Grunde dasselbe: `sed" s /. * '\ ([^'] \ + \) '. * / \ 1 / "` Peter.O vor 12 Jahren 1
Dies funktioniert nicht bei mehrzeiliger Eingabe. Dazu benötigen Sie: `sed -n" s /.* '\ ([^'] \ + \) '. * / \ 1 / p "` phreakhead vor 12 Jahren 2
26
Aldrik

Während grep keine bestimmte Gruppe ausgeben kann, können Sie Lookahead und hinter Assertions verwenden, um das zu erreichen, was Sie danach wollen:

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

`grep -P` ist nicht auf allen Plattformen verfügbar. Wenn ja, ist die Verwendung von Lookahead / Behind eine sehr gute Möglichkeit, das Problem zu lösen. Sébastien vor 12 Jahren 6
Is grep intelligent with the look-behind assertions? How does it perform with long look-behinds? Is it integrating the look-behinds into some sort of ["suffix tree"](http://en.wikipedia.org/wiki/Suffix_tree) with the rest of the regex? Ross Rogers vor 12 Jahren 1
2
drewk

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

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

Nur GNU grep.