2009-12-25 12 views
33

Ich möchte den Befehl system in einem awk-Skript ausführen und dessen Ausgabe in einer Variablen speichern. Ich habe versucht, dies zu tun, aber die Ausgabe des Befehls geht immer an die Shell und ich kann sie nicht erfassen. Irgendwelche Ideen, wie das gemacht werden kann?Zuweisung der Ausgabe des Systembefehls an die Variable

Beispiel:

$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/} 

Sollte das strip Systembefehl aufrufen und statt der Ausgabe an die Schale zu senden, sollte die Ausgabe zurück zu $1 für weitere Verarbeitung zuzuweisen. Rignt sendet nun die Ausgabe an die Shell und weist den Retode des Befehls $1 zu.

+1

nit: Der Ausgang nicht an die Schale geht, es wird an das Terminal /Konsole. Die Shell liest keine Ausgabe ihrer untergeordneten Elemente - sie teilen nur Dateideskriptoren, die demselben tty zugeordnet sind. –

Antwort

23

Herausgefunden.

Wir verwenden awk des Two-way I/O

{ 
    "strip $1" |& getline $1 
} 

geht $ 1 abzustreifen und die getline nimmt Ausgabe von Band 1 $ zurück

+1

Wenn Sie den gleichen Befehl mehrmals aufrufen müssen, müssen wir den Befehl schließen (http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_26.html#SEC29) – mcoolive

49

Hinweis: Koprozeß ist GNU spezifische awk. Auf jeden Fall eine andere Alternative ist mit getline

cmd = "strip "$1 
while ((cmd | getline result) > 0) { 
    print result 
} 
close(cmd) 
+0

Danke. Auf diese Weise kann ich die & von meiner Antwort entfernen. Sieht cooler aus. Aber ich schreibe nur für die Verwendung in Linux, so dass die Nichtverfügbarkeit von Gawk kein Problem sein sollte? – Sahas

+0

ja, sollte kein Problem sein. Trotzdem sollten Sie die Dokumentation überprüfen und prüfen, ob Coprocess nur in bestimmten Versionen von gawk verfügbar ist. Ich kann mich nicht an meinen Kopf erinnern – ghostdog74

+0

Ab Version 3.1. RedHat hat 3.1.5. Jedenfalls werde ich die von Ihnen vorgeschlagene Methode verwenden, es sei denn, ich möchte etwas an stdin des Befehls senden. In diesem Fall ist Coprocess hilfreich. – Sahas

5
gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}' 
+13

Wenn Sie Antworten veröffentlichen, sollten Sie die verschiedenen Teile erklären (was Sie getan haben und warum es funktioniert). Damit andere von Ihrer Antwort lernen können. Für manche Leute wäre diese Linie selbsterklärend. Aber für andere ist es schwer zu folgen, was Sie genau getan haben. –

16

Um einen Systembefehl in awk laufen Sie entweder system() oder cmd | getline verwenden können.

Ich ziehe cmd | getline weil es Ihnen erlaubt, den Wert in eine Variable zu fangen:

$ awk 'BEGIN {"date" | getline mydate; close("date"); print "returns", mydate}' 
returns Thu Jul 28 10:16:55 CEST 2016 

Allgemeiner Sie den Befehl in eine Variable festlegen:

awk 'BEGIN { 
     cmd = "date -j -f %s" 
     cmd | getline mydate 
     close(cmd) 
    }' 

Hinweis ist es wichtig, Verwenden Sie close(), um zu verhindern, dass ein "zu viele geöffnete Dateien erstellen" -Fehler auftritt, wenn Sie mehrere Ergebnisse haben (danke mateuscb für das Aufzeigen in Kommentaren).


Mit system(), die Befehlsausgabe automatisch gedruckt wird und der Wert, den Sie fangen können, ist sein Rückgabecode:

$ awk 'BEGIN {d=system("date"); print "returns", d}' 
Thu Jul 28 10:16:12 CEST 2016 
returns 0 
$ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}' 
ls: cannot access asdfasdfasd: No such file or directory 
returns 2 
+2

+1 für das Hinzufügen von 'close()', wenn Sie es nicht hinzufügen und mehrere Ergebnisse haben, können Sie "macht zu viele offene Dateien" erhalten. Wenn Sie einen längeren Befehl haben, können Sie 'cmd =" ​​date -j -f% s "; cmd | getline mydate; schließen (cmd) ' – mateuscb

+1

@mateuscb vielen dank für ihr feedback. Ich habe die Frage aktualisiert, um Ihre nützlichen Kommentare hinzuzufügen. – fedorqui

+1

Danke für die Erinnerung an close() Befehl. Es hilft sehr. Ohne close(), bekomme ich manchmal falsche Ergebnisse für mehrere Ergebnisse. Mit dem Schließen von(). Meine Ergebnisse für mehrere Termine werden alle korrekt angezeigt. – csu007

Verwandte Themen