Ich möchte die kürzeste Übereinstimmung finden und das Muster sollte ungefähr so aussehen:
<car ... model=BMW ...>
...
...
...
</car>
... bedeutet ein beliebiges Zeichen und die Eingabe ist mehrzeilig.
Sie suchen nach einem nicht gierigen (oder faulen) Match. Um eine nicht gierige Übereinstimmung in regulären Ausdrücken zu erhalten, müssen Sie den Modifizierer ?
Nach dem Quantifizierer verwenden. Zum Beispiel können Sie .*
In .*?
Ändern.
Standardmäßig unterstützt grep
keine non-greedy-Modifikatoren, Sie können jedoch grep -P
Verwenden, um die Perl-Syntax zu verwenden.
Tatsächlich das .*?
funktioniert nur in Perl
. Ich bin nicht sicher, was die äquivalente grep erweiterte Regexp-Syntax sein würde. Glücklicherweise können Sie Perl-Syntax mit grep verwenden, also grep -P
würde funktionieren aber grep -E
das ist das gleiche wie egrep
würde nicht funktionieren (es wäre gierig).
Siehe auch: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep
Für eine nicht gierige Übereinstimmung in grep
können 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 zuerst durch xargs
. Verwenden Sie für die Leistung ripgrep
.
Mein Grep, der nach dem Ausprobieren von Sachen in diesem Thread funktioniert:
echo "hi how are you " | grep -shoP ".*? "
Stellen Sie einfach sicher, dass Sie an jede Ihrer Zeilen ein Leerzeichen anhängen
(Meins war eine zeilenweise Suche, um Wörter auszuspucken)
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>
Auf diese Weise können Sie im folgenden Text car1 und car2 abgleichen
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>