2009-12-25 4 views
33

Voglio eseguire il comando system in uno script awk e ottenere il suo output memorizzato in una variabile. Ho cercato di farlo, ma l'output del comando va sempre alla shell e non sono in grado di catturarlo. Qualche idea su come questo può essere fatto?Assegnazione dell'output del comando di sistema alla variabile

Esempio:

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

deve chiamare il comando del sistema strip, invece di inviare l'uscita a guscio, dovrebbe assegnare l'uscita ritorna $1 per ulteriore elaborazione. Riavvia ora, invia l'output alla shell e assegna il retcode del comando a $1.

+1

nit: l'uscita non è andare a guscio, sta andando al terminale/console. La shell non legge alcuno dei risultati dei suoi figli - essi condividono solo descrittori di file che sono associati allo stesso tty. –

risposta

23

Capito.

Usiamo di awk Two-way I/O

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

passa $ 1 a lamelle e getline prende uscita dalla striscia di nuovo a $ 1

+1

Se è necessario chiamare più volte lo stesso comando, è necessario chiudere il comando (http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_26.html#SEC29) – mcoolive

49

Nota: coprocesso è GNU awk specifica. Comunque un'altra alternativa sta usando getline

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

Grazie. In questo modo, posso rimuovere il & dalla mia risposta. Sembra più fresco. Ma sto scrivendo solo per l'utilizzo in Linux, quindi l'indisponibilità di gawk non dovrebbe essere un problema? – Sahas

+0

sì, non dovrebbe essere un problema. ancora dovresti controllare la documentazione e vedere se coprocess è disponibile solo in alcune versioni di gawk. Non riesco a ricordare in cima alla mia testa – ghostdog74

+0

Dalla versione 3.1. RedHat ha 3.1.5. Ad ogni modo userò il modo in cui mi hai suggerito, a meno che non desideri inviare qualcosa a stdin del comando, nel qual caso il coprocesso è utile. – Sahas

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

Se pubblichi le risposte dovresti spiegare le diverse parti (cosa hai fatto e perché funziona). In modo che altri possano imparare dalla tua risposta. Per alcune persone questa linea si spiegherebbe da sola. Ma per gli altri è difficile seguire ciò che hai fatto esattamente. –

16

Per eseguire un comando di sistema in awk è possibile utilizzare system() o cmd | getline.

preferisco cmd | getline perché permette di cogliere il valore in una variabile:

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

Più in generale, è possibile impostare il comando in una variabile:

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

Nota è importante utilizzare close() per evitare di ottenere un errore "rende troppi file aperti" se si dispone di più risultati (grazie mateuscb per averlo indicato nei commenti).


Utilizzando system(), l'output del comando viene stampato automaticamente e il valore che si può prendere è la sua codice di ritorno:

$ 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 per aggiungere 'close()', se non lo aggiungi e hai più risultati, potresti ottenere "rende troppi file aperti". Se hai un comando più lungo, puoi fare 'cmd =" ​​date -j -f% s "; cmd | getline mydate; chiudi (cmd) ' – mateuscb

+1

@mateuscb molte grazie per il tuo feedback. Ho aggiornato la domanda per includere i tuoi commenti utili. – fedorqui

+1

Grazie per aver ricordato il comando close(). Aiuta molto. Senza mettere vicino(), a volte ottengo risultati di date errate per più risultati. Con mettere vicino(). i miei risultati con più date sono tutti visualizzati correttamente. – csu007