Ich möchte einen nicht gierigen Mustervergleich (regulärer Ausdruck) durchführen awk
. Hier ist ein Beispiel:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
Ist es möglich, einen regulären Ausdruck zu schreiben, der die kürzere Zeichenfolge auswählt?
@article{gjn,
anstelle dieser langen Zeichenfolge ?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Ich möchte dieses Ergebnis erhalten:
Author = {Grzegorz J. Nalepa},
Ich habe ein anderes Beispiel:
echo " , article {gjn, Author = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); drucken }' ↑ ↑ ^^^^^
Beachten Sie, dass ich die @
Zeichen an ,
der ersten Stelle sowohl der Eingabezeichenfolge als auch des regulären Ausdrucks in Komma ( ) geändert habe (und auch in geändert .*
habe [^,]*
). Ist es möglich, einen regulären Ausdruck zu schreiben, der die kürzere Zeichenfolge auswählt?
, Author = {Grzegorz J. Nalepa},
anstelle der längeren Saite ?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Ich möchte dieses Ergebnis erhalten:
,article{gjn
awk
regular-expression
nowy1
quelle
quelle
Author
nach einem Komma und Leerzeichen, gefolgt von einem Leerzeichen gefolgt von=
gefolgt von Leerzeichen , gefolgt von{
gefolgt von einem beliebigen nicht}
gefolgt}
, obwohl dies (unter anderem) erfordert , dass Sie nicht verschachtelt werden können{}
innerhalb des= { ... }
Teils.Antworten:
Wenn Sie
@
und bis zu dem ersten,
danach auswählen möchten , müssen Sie es als angeben@[^,]*,
Darauf
@
folgt eine beliebige Anzahl (*
) von Nicht-Kommas ([^,]
), gefolgt von einem Komma (,
).Dieser Ansatz funktioniert als Äquivalent zu
@.*?,
, aber nicht für Dinge wie@.*?string
, bei denen das, was danach ist, mehr als ein einzelnes Zeichen ist. Das Negieren eines Zeichens ist einfach, aber das Negieren von Zeichenfolgen in regulären Ausdrücken ist viel schwieriger .Ein anderer Ansatz besteht darin, Ihre Eingabe vorab zu verarbeiten, um das
string
Zeichen durch ein Zeichen zu ersetzen oder voranzustellen, das ansonsten in Ihrer Eingabe nicht vorkommt:Wenn Sie nicht garantieren können, dass die Eingabe kein Ersatzzeichen enthält (siehe
\1
oben), können Sie einen Escape-Mechanismus verwenden:Das funktioniert für feste
string
s, aber nicht für beliebige reguläre Ausdrücke wie für das Äquivalent von@.*?foo.bar
.quelle
Es gibt bereits mehrere gute Antworten, die Workarounds für
awk
die Unfähigkeit bieten, nicht-gierige Übereinstimmungen durchzuführen. Daher gebe ich einige Informationen zu einer alternativen Möglichkeit, dies mit Perl-kompatiblen regulären Ausdrücken (PCRE) zu tun . Beachten Sie, dass die meisten einfachen "Match and Print" -Skripten mit der Befehlszeilenoptionawk
einfach neu implementiertperl
werden-n
können und komplexere Skripten mit dem a2p Awk to Perl-Übersetzer konvertiert werden können .Perl hat einen nicht-gierigen Operator, der in Perl-Skripten und in allem, was PCRE verwendet, verwendet werden kann. Zum Beispiel auch in der
-P
Option von GNU grep implementiert .PCRE ist nicht identisch mit Perls regulären Ausdrücken, aber es ist sehr nah. Es ist eine beliebte Wahl für eine Bibliothek mit regulären Ausdrücken für viele Programme, da es sehr schnell ist und die Perl-Verbesserungen für erweiterte reguläre Ausdrücke sehr nützlich sind.
Aus der perlre (1) -Manpage :
quelle
Dies ist ein alter Beitrag, aber die folgenden Informationen könnten für andere hilfreich sein.
Es gibt eine zugegebenermaßen grobe Möglichkeit, in awk einen nicht gierigen RE-Abgleich durchzuführen. Die Grundidee besteht darin, die Match-Funktion (String, RE) zu verwenden und die Größe des Strings schrittweise zu verringern, bis der Match fehlschlägt, etwa (ungetestet):
quelle
Für allgemeine Ausdrücke kann dies als nicht gierige Übereinstimmung verwendet werden:
Ich benutze dies basierend auf der Antwort von @ JimMellander.
smatch
verhält sich wiematch
:quelle
Awk bietet keine Möglichkeit, nicht gierige Übereinstimmungen durchzuführen. Möglicherweise können Sie jedoch die gewünschte Ausgabe erhalten. Der Vorschlag von sch wird für diese Zeile funktionieren. Wenn Sie sich nicht auf ein Komma verlassen können, sondern "Autor" immer der Anfang von dem ist, was Sie wollen, können Sie dies tun:
Wenn die Anzahl der Zeichen vor dem Autor immer gleich ist, können Sie dies tun:
Sie müssen nur wissen, wie Ihre Daten im gesamten Satz aussehen.
quelle
Es gibt immer einen Weg. Das gegebene Problem kann ziemlich einfach gelöst werden, indem Kommas als Trennzeichen verwendet werden.
Wenn die Anzahl der Felder variiert, wird normalerweise etwas Besseres benötigt. In solchen Fällen lohnt es sich oft, ein Stoppwort zu finden, da Sie damit alles aus der Zeile herausschneiden können. Im Kontext des Beispiels ist hier, was ich mit Stoppwörtern meine.
quelle
Ich weiß, dass dies ein alter Beitrag ist. Aber hier ist etwas, das awk nur wie gewünscht als OP verwendet:
A = @ article {gjn2010jucs, Author = {Grzegorz J. Nalepa},
echo $ A | awk 'sub (/ @ [^,] * /, "")'
Ausgabe:,
Autor = {Grzegorz J. Nalepa},
quelle