Ich möchte einen Teilstring extrahieren, in dem ein bestimmtes Muster aus der durch Pfeifen getrennten Datei vorhanden ist.
awk -F ":" '/REWARD REQ. SERVER HEADERS/{print $1, $2, $3, $4}' sample_profile.txt
Hier 'REWARD REQ. SERVER HEADERS 'ist ein Muster, das in der Datei gesucht werden soll und die ersten 4 Teile in einer durch Doppelpunkt getrennten Zeile ausgeben soll.
Nun möchte ich die bash-Variable senden, um als Muster zu fungieren. also habe ich den folgenden Befehl verwendet, aber es funktioniert nicht.
awk -v pat="$pattern" -F ":" '/pat/{print $1, $2 , $3, $4 } sample_profile.txt
Wie kann ich -v
und -F
in einem einzigen awk
-Befehl verwenden?
Das Problem hat hier nicht mit -F
zu tun.
Das Problem ist die Verwendung von /pat/
, wenn pat
eine Variable sein soll. Wenn Sie /pat/
sagen, versteht awk
es als wörtliches "pat", also versucht es, die Zeilen mit der Zeichenfolge "pat" abzugleichen.
Wenn Sie das Muster über eine Variable bereitstellen möchten, müssen Sie ~
wie folgt verwenden:
awk -v pat="$pattern" '$0 ~ pat'
Alles in allem sollte Ihr Code sein:
awk -v pat="$pattern" -F ":" '$0~pat{print $1, $2, $3, $4 }' file
# ^^^^^^
Siehe ein Beispiel:
Gegeben diese Datei:
$ cat file
hello
this is a var
hello bye
Suchen wir nach Zeilen, die "Hallo" enthalten:
$ awk '/hello/' file
hello
hello bye
Versuchen wir nun, nach "pat" zu suchen, das in einer Variablen enthalten ist, wie Sie es getan haben:
$ awk -v pat="hello" '/pat/' file
$ # NO MATCHES!
Verwenden wir nun den Ausdruck $0 ~ pat
:
$ awk -v pat="hello" '$0~pat' file
hello # WE MATCH!
hello bye
Natürlich können Sie solche Ausdrücke verwenden, um nur ein Feld zu finden und awk -v pat="$pattern" '$2 ~ pat' file
usw. zu sagen.
Von GNU Awk Benutzerhandbuch → 3.1 So verwenden Sie reguläre Ausdrücke :
Wenn ein Regex in Schrägstriche eingeschlossen ist, wie zum Beispiel/foo /, nennen wir es eine Regex-Konstante, ähnlich wie 5.27 eine numerische Konstante und "foo" eine String-Konstante.
And GNU Awk Benutzerhandbuch → 3.6 Verwenden von Dynamic Regexps :
Die rechte Seite eines '~' oder '! ~' Operators muss kein Regex sein konstant (d. h. eine Zeichenfolge zwischen Schrägstrichen). Es kann beliebig sein Ausdruck. Der Ausdruck wird ausgewertet und in eine Zeichenfolge umgewandelt, wenn notwendig; Der Inhalt der Zeichenfolge wird dann als regulärer Ausdruck verwendet. EIN Der auf diese Weise berechnete reguläre Ausdruck wird als dynamischer regulärer Ausdruck oder berechneter Wert bezeichnet. regulärer Ausdruck:
BEGIN { digits_regexp = "[[:digit:]]+" } $0 ~ digits_regexp { print }
Dadurch wird für digits_regexp ein regulärer Ausdruck gesetzt, der eine oder mehrere Ziffern beschreibt und testet, ob der Eingabedatensatz mit diesem regulären Ausdruck übereinstimmt.
awk -v pat="$pattern" -F":" '$0 ~ pat { print $1, $2, $3, $4 }' sample_profile.txt
Sie können die Variable nicht in der Regex-//
-Notation verwenden (sie kann nicht von der Suche nach pat
unterschieden werden); Sie müssen angeben, dass die Variable mit dem Operator ~
(übereinstimmend) eine reguläre Ausdrücke ist.
Dies ist eine Art Hack, aber es macht die Sache für mich ein bisschen einfacher.
cmd="awk '/$pattern/'"
eval $cmd
wenn Sie den String zuerst zu einem String machen, können Sie ihn über die Grenzen von awk hinaus bearbeiten