Wie kann man awk-Anweisungen ausdrucken?

1062
tjt263

Okay, hier ist ein kurzes Beispiel. Ich isoliere die IPV4 eines Hosts in drei Schritten:

ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 DOWN wlan0 UP 192.168.0.101/24 fe80::9fcd:45fb:1e0f:a1cc/64 
ip -br a | awk '/wlan0/ ' 192.168.0.101/24 
ip -br a | awk '/wlan0/ ' | awk -F '/' '' 192.168.0.101 

Anstatt eine zweite Instanz von aufzurufen awk(leitet die Ausgabe von einer in die nächste); Wie kann das alles auf einmal gemacht werden?


Ich wollte nur sagen: Die Frage ist nicht die Analyse der Ausgabe von ip. Ich brauchte nur ein kurzes Beispiel, um die Frage zu veranschaulichen. Dies war das erste, was mir einfiel. Die eigentliche Frage ist im Titel zusammengefasst.

Wie auch immer, für was es wert ist (ich muss es überprüfen, aber ich bin mir ziemlich sicher); Das habe ich in der letzten Zeit gemacht:

ip -br a s dev wlan0 | awk -F '[ /]*' '' 192.168.0.101 
5

5 Antworten auf die Frage

2
Stephen Rauch

Sie können gsub wie folgt verwenden :

ip -br a | awk '/wlan0/ ' 
2
John1024

Ändern Sie einfach die Definition des Feldtrennzeichens, um sowohl Leerzeichen als auch /:

$ ip -br a | awk -F'[[:blank:]/]+' '/wlan0/' 192.168.0.101 

Die Option -F'[[:blank:]/]+'weist awk an, eine beliebige Kombination von Leerzeichen, Tabulatoren oder Schrägstrichen als Feldtrennzeichen bei der Eingabe zu verwenden.

Dies gibt das korrekte Ergebnis für das `ip`-Beispiel. Das OP sagt jedoch, dass "ip" nur ein illustratives Beispiel ist. Die eigentliche Frage ist: Wie machst du `awk '' | awk -F '/' '' 'in einem einzigen `awk'-Befehl, und diese Antwort schlägt fehl, wenn das erste oder das zweite (durch Leerzeichen getrennte) Wort in der Eingabezeile ein` / `enthält. Insbesondere wird in diesem Fall das dritte Unterfeld des ersten Wortes oder das erste oder zweite Unterfeld des zweiten Wortes ausgegeben. G-Man vor 6 Jahren 0
2
Chris

In diesem Fall ist es wahrscheinlich am einfachsten, mehrere Trennzeichen mithilfe eines regulären Ausdrucks festzulegen:

ip -br a | awk -F '[\t /]*' '/wlan0/ ' 

Dadurch wird das Feldtrennzeichen aus beliebigen Zeichenfolgen /, Leerzeichen oder Registerkarten und das dritte Feld wird gedruckt.

Um zwei beliebige Befehle auszuführen, die Sie möchten, müssen Sie die gesamte Programmiersprache awk lernen. Ich würde dagegen empfehlen - ich bin sicher, Sie haben mit Ihrer Zeit bessere Dinge zu tun.

Dies gibt das korrekte Ergebnis für das `ip`-Beispiel. Das OP sagt jedoch, dass "ip" nur ein illustratives Beispiel ist. Die eigentliche Frage ist: Wie machst du `awk '' | awk -F '/' '' 'in einem einzigen `awk'-Befehl, und diese Antwort schlägt fehl, wenn das erste oder das zweite (durch Leerzeichen getrennte) Wort in der Eingabezeile ein` / `enthält. Insbesondere wird in diesem Fall das dritte Unterfeld des ersten Wortes oder das erste oder zweite Unterfeld des zweiten Wortes ausgegeben. G-Man vor 6 Jahren 0
@ G-Man Ich stimme vollkommen zu, dass mein illustratives Beispiel keine vollständige Lösung ist, sondern nur ein Trick, der in diesem Fall funktioniert. Aber das ist mein Punkt - es gibt * keine * allgemeine Methode zum Verketten von 'awk'-Anweisungen: Sie brauchen für jeden einen eigenen "Trick". Also "um beliebige * beliebige * Befehle auszuführen, müssen Sie die gesamte Programmiersprache awk lernen." Chris vor 6 Jahren 0
2
Joe

Obwohl die anderen Antworten das zugrunde liegende Problem lösen, beantworten sie nicht wirklich die Frage "Wie verkette ich awk-Druckaussagen?"

Für diese Art von Problem lautet die Antwort "Sie tun es nicht". Sie verwenden den Rest der Sprache, um die Quelle zu manipulieren, bis Sie das gewünschte Ergebnis erhalten - was die beiden anderen Antworten tun. Sie dienen nur printzur Ausgabe des Endergebnisses.

Nachdem Sie ein anfängliches Bereichsmuster angegeben haben /wlan0/(oder ( /^wl/in meinem Fall, weil mein WiFi einen anderen Namen hat), kann Ihre Aktion, der Code darin {}, nur auf Eingabezeilen angewendet werden, die diese Zeichenfolge enthalten.

Sobald Sie das haben, können Sie mit dieser Eingabezeile alles tun, was Sie brauchen.

ip -br a | \ awk ' /^wl/ { ip1 = $3 gsub(/\/.*/, "", ip1) print ip1 } ' 

Dieser Code nimmt das gewünschte Feld in eine Variable, bearbeitet den Inhalt dieser Variablen und druckt ihn dann.

Die andere Antwort macht das gleiche effizienter, aber dies veranschaulicht einen allgemeineren Fall, in dem andere Schritte hinzugefügt werden können. Sie können das Ergebnis sogar speichern, um es später mit etwas in einer anderen Eingabezeile usw. zu verwenden.

Für etwas, das tatsächlich mehr nach "print chaining" aussehen könnte, hat awk eine sprintf()Funktion, die einen formatierten Ausdruck seiner Eingabe in eine Variable zur weiteren Verarbeitung ausführen kann.

Wenn Sie mehr als eine Sache in einer Zeile drucken, kann Ihr Code mehrere printf()Anweisungen ohne Zeilenumbruch bis zum letzten verwenden, um eine Ausgabezeile Stück für Stück zu erstellen.

Dies ist bis jetzt die beste Antwort auf die Frage: Wie machst du `awk '' | awk -F '/' '' 'in einem einzigen `awk'-Befehl? Aber wie würden Sie das zu awk '| awk -F '/' '' `? Um zum Beispiel "fox" zu drucken, geben Sie als Eingabe "wlan0 foo / bar the / quick / brown / fox / jumps / over / the Lazy / dog" ein. G-Man vor 6 Jahren 0
0
G-Man

Dies ist etwas im Geist des Stephen Rauchs Antwort und Joe Antwort, aber besser:

awk '/wlan0/ ' 

Dies nimmt das dritte Feld ( $3) und verwendet splites /als Trennzeichen. Die Komponenten gehen in ein Array aund die Anzahl der Unterfelder wird zurückgegeben. (In diesem Snippet ignoriere ich den Rückgabewert.) Also  a[1]das erste /begrenzte Unterfeld des dritten Feldes.

Dies lässt sich leichter verallgemeinern als die anderen Antworten. Zum Beispiel, wenn Ihre Eingabe ist

Es war einmal eine Mitternacht trostlos, während ich schwach und müde dachte Über viele urige und neugierige Bände von vergessener Überlieferung ... wlan0 foo / bar die / schnell / braun / fox / sprünge / über / die faule / hund Während ich nickte und beinahe ein Nickerchen machte, kam plötzlich ein Klopfen. Ab und zu klopft es sanft an meiner Zimmertür.

dann der Befehl

awk '/wlan0/ ' 

druckt das vierte Unterfeld des dritten Feldes der dritten Zeile ( fox), nachdem der Rückgabewert von split überprüft wurde, um zu überprüfen, ob (mindestens) vier Unterfelder vorhanden sind. Dh das ist wie

awk '/wlan0/ ' | awk -F '/' '' 

in einem einzigen awkBefehl mit Fehlerprüfung.