Antworten:
Sie suchen ein nicht gieriges (oder faules) Match. Um eine nicht gierige Übereinstimmung in regulären Ausdrücken zu erhalten, müssen Sie den Modifikator ?
nach dem Quantifizierer verwenden. Zum Beispiel können Sie ändern .*
zu.*?
.
Standardmäßig werden grep
keine nicht gierigen Modifikatoren unterstützt, Sie können grep -P
jedoch die Perl-Syntax verwenden.
.
dem Zeilenumbrüche abgeglichen werden können, als DOTALL- oder Einzeilenmodus bezeichnet . Ruby ist der einzige, der es mehrzeilig nennt . In den anderen Varianten ist Multiline der Modus, in dem die Anker ( ^
und $
) an den Liniengrenzen übereinstimmen können. Ruby hat keinen äquivalenten Modus, da sie in Ruby immer so funktionieren.
-P
war eine völlig neue für mich, ich habe mich jahrelang glücklich gefreut und nur -E
... so viele verschwendete Jahre benutzt! - Hinweis für sich selbst: Lesen Sie Manpages als (noch mehr!) Normale Sache neu, Sie verdauen nie genug Schalter und Optionen.
grep
dies nicht unterstützt -P
. Wenn Sie es jedoch verwenden egrep
, können Sie das .*?
Muster verwenden, um das gleiche Ergebnis zu erzielen. egrep -o 'start.*?end' text.html
-P
, -E
würde jedoch aufrufen, egrep
dass die vorgeschlagenen Funktionen einwandfrei .*?
funktionieren.
Eigentlich funktioniert das .*?
nur in perl
. Ich bin mir nicht sicher, wie die entsprechende grep-erweiterte Regexp-Syntax aussehen würde. Glücklicherweise können Sie die Perl-Syntax mit grep verwenden, grep -P
würde also funktionieren, aber grep -E
das ist dasselbe, egrep
was nicht funktionieren würde (es wäre gierig).
Siehe auch: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep -P
funktioniert nicht in GNU grep 2.9 - habe es gerade versucht (es macht keinen Fehler, wendet nur stillschweigend das nicht an ?
. Intertestly auch nicht die nicht-Klasse zB:env|grep '[^\=]*\='
grep -P
Option oder keinen pgrep
Befehl, aber es egrep
funktioniert hervorragend.
pgrep
Befehl auf meiner OS X 10.9-Box, aber es ist ein völlig anderes Programm, dessen Zweck darin besteht, "Prozesse nach Namen zu finden oder zu signalisieren".
Mein grep, der funktioniert, nachdem ich Sachen in diesem Thread ausprobiert habe:
echo "hi how are you " | grep -shoP ".*? "
Stellen Sie einfach sicher, dass Sie jeder Ihrer Zeilen ein Leerzeichen hinzufügen
(Meins war eine zeilenweise Suche, um Wörter auszuspucken)
-shoP
schöne Gedächtnisstütze :)
echo "bbbbb" | grep -shoP 'b.*?b'
ist ein bisschen eine Lernerfahrung. Einzige Sache, die bei mir auch explizit faul funktioniert hat.
grep
Für nicht gierige Übereinstimmungen in können grep
Sie eine negierte Zeichenklasse verwenden. Versuchen Sie mit anderen Worten, Platzhalter zu vermeiden.
Um beispielsweise alle Links zu JPEG-Dateien aus dem Seiteninhalt abzurufen, verwenden Sie Folgendes:
grep -o '"[^" ]\+.jpg"'
Um mit mehreren Zeilen umzugehen, leiten Sie die Eingabe xargs
zuerst durch . Verwenden Sie für die Leistung ripgrep
.
Die kurze Antwort verwendet den nächsten regulären Ausdruck:
(?s)<car .*? model=BMW .*?>.*?</car>
Eine (etwas) kompliziertere Antwort lautet:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Dies ermöglicht es, car1 und car2 im folgenden Text abzugleichen
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
Entschuldigung, ich bin 9 Jahre zu spät, aber das könnte für die Zuschauer im Jahr 2020 funktionieren.
Angenommen, Sie haben eine Zeile wie "Hello my name is Jello"
. Jetzt möchten Sie die Wörter finden, die mit 'H'
und 'o'
mit einer beliebigen Anzahl von Zeichen dazwischen beginnen und enden . Und wir wollen keine Zeilen, wir wollen nur Worte. Dafür können wir den Ausdruck verwenden:
grep "H[^ ]*o" file
Dies gibt alle Wörter zurück. Dies funktioniert folgendermaßen: Es werden alle Zeichen anstelle von Leerzeichen dazwischen zugelassen. Auf diese Weise können wir mehrere Wörter in derselben Zeile vermeiden.
Jetzt können Sie das Leerzeichen durch ein beliebiges anderes Zeichen ersetzen. Angenommen, die erste Zeile war "Hello-my-name-is-Jello"
, dann können Sie Wörter mit dem Ausdruck erhalten:
grep "H[^-]*o" file
Ich weiß, dass es ein bisschen tot ist, aber ich habe gerade bemerkt, dass das funktioniert. Es hat sowohl Bereinigung als auch Bereinigung von meiner Ausgabe entfernt.
> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20