web-dev-qa-db-fra.com

Affectation de la sortie de la commande système à une variable

Je veux exécuter la commande system dans un script awk et obtenir sa sortie stockée dans une variable. J'ai essayé de le faire, mais la sortie de la commande va toujours au Shell et je ne suis pas en mesure de la capturer. Des idées sur la façon dont cela peut être fait?

Exemple:

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

Doit appeler la commande système strip et au lieu d'envoyer la sortie au shell, doit la renvoyer à $1 pour plus de traitement. Rignt maintenant, il envoie la sortie à Shell et attribue le retcode de la commande à $1.

45
Sahas

Compris.

Nous utilisons les awk's E/S bidirectionnelles

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

passe 1 $ à supprimer et la ligne de lecture reprend la sortie de la bande à 1 $

28
Sahas

Remarque: Coprocess est GNU spécifique à awk. Quoi qu'il en soit, une autre alternative utilise getline

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

L'appel de close(cmd) empêchera awk de renvoyer cette erreur après un certain nombre d'appels:

fatal: impossible d'ouvrir le tube `... '(Trop de fichiers ouverts)

56
ghostdog74

Pour exécuter une commande système dans awk, vous pouvez utiliser system() ou cmd | getline .

Je préfère cmd | getline Car il vous permet d'attraper la valeur dans une variable:

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

Plus généralement, vous pouvez définir la commande dans une variable:

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

Notez qu'il est important d'utiliser close() pour éviter d'obtenir une erreur "crée trop de fichiers ouverts" si vous avez plusieurs résultats (merci mateuscb pour l'avoir signalé dans les commentaires).


En utilisant system(), la sortie de la commande est imprimée automatiquement et la valeur que vous pouvez saisir est son code retour:

$ 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
28
fedorqui
gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}'
6
Ryan Liu

Vous pouvez l'utiliser lorsque vous devez traiter une sortie grep:

echo "some/path/exex.c:some text" | awk -F: '{ "basename "$1"" |& getline $1; print $1 " ==> " $2}'

option -F: dire à awk d'utiliser : comme séparateur de champ

"basename "$1"" exécute la commande Shell basename sur le premier champ

|& getline $1 lit la sortie de la précédente commande Shell dans le sous-flux

output:
exex.c ==> some text
3
cy8g3n