awk: Ausdrücke durch logisches ODER kombinieren

awk: Ausdrücke durch logisches ODER kombinieren

Ich möchte zwei awk-Ausdrücke kombinieren (logisch ODER). Separat funktionieren beide einwandfrei. Der erste Ausdruck druckt die Zeile direkt vor dem Suchbegriff. Der zweite Ausdruck druckt nur die Zeile, die ein Sonderzeichen enthält. Wenn ich beide Ausdrücke mit einem ODER-Operator kombiniere, erhalte ich den Fehler '

^ unerwarteter Zeilenumbruch oder Zeichenfolgenende

'

awk '(({$0~/\*/; print a; a=$0}) || (/\→/))' file.txt

file.txt sieht folgendermaßen aus:

foo
*
bla
bla
bar→
bar→
foo
*
bla
bla
bar→
foo
*
bla
bar→
bar→

Erwartetes Ergebnis:

foo
bar→
bar→
foo
bar→
foo
bar→
bar→

Antwort1

Wenn Sie Ihre Anforderungen lesen, beschreiben Siezweiverschiedene Ausdrücke fürzwei verschiedene Jobs. Du sagst :

First expression prints the line right before the search term
Second expression just prints the line that contains a special character

Das bedeutet, dass diese beiden Ausdrücke NICHT mit ODER kombiniert werden können. Sie kombinieren mit ODER-Ausdrücken, die dieselbe Aktion ausführen.

Die richtige Antwort laut Ihrer Formulierung lautet daher:

$ awk '/\*/{print a}{a=$0}/\→/' <<<"$a"
foo
bar→
bar→
foo
bar→
foo
bar→
bar→

Wenn Sie wirklich eine ODER-Bedingung verwenden müssen, um die gleiche Aktion für zwei verschiedene Bedingungen auszuführen, können Sie es auch so machen:

awk '/[*→]/{print a; a=$0}' file

Antwort2

Mit dem Hinweis zum Ausdrucken dervorherigeZeile, wenn ein Sternchen angezeigt wird, und dieaktuellZeile, wenn Sie ein : sehen .

awk '/\*/ {print prev} /\→/ {print} {prev=$0}' file.txt

/pattern/ {action}ist die Abkürzung für $0 ~ /pattern/ {action}. Die erste Aktion druckt die Variable prev, wenn ein Sternchen in der Zeile steht, die zweite druckt die aktuelle Zeile, wenn ein Pfeil vorhanden ist, und schließlichbedingungslosSpeichern Sie die aktuelle Zeile unter prev, damit sie zum Drucken verfügbar ist, wenn die nächste Zeile übereinstimmt.

Antwort3

Das sollte funktionieren:

awk '/\*/ || /→/ {print}' /path/to/file

Antwort4

Dies führt zu den erwarteten Ergebnissen, die Sie angeben. Sie müssen das * nicht maskieren, da wir uns auf das Verhalten „In POSIX awk und gawk stehen die Operatoren ‚*‘, ‚+‘ und ‚?“ verlassen können, wenn im regulären Ausdruck, der ihnen vorangeht, nichts steht.“ hier, weitere Details unterhttps://www.gnu.org/software/gawk/manual/gawk.html#Regexp

$ awk '/*/||/→/' file.txt
foo*
bar→
bar→
foo**
bar→
foo*
bar→
bar→
$

Stattdessen grep verwenden:

$ grep -E '\*|→' file.txt

verwandte Informationen