Existe-t-il 2 façons de définir des vars awk via la ligne de commande?

10

J'ai remarqué un awkexemple O'Reilly (1997) qui a assigné une variable awk en la plaçant sur la ligne de commande après le texte du programme. Cela fonctionne, mais je ne trouve pas cette syntaxe dans man / info awk . Je viens de le manquer; est-il privé ...? La seule syntaxe que j'ai vue dans le manuel est l' -voption.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Production: cat dog

Peter.O
la source

Réponses:

11

C'est en fait dans POSIX awk(lien vers POSIX 2008, les versions précédentes l'avaient aussi je crois). -vest décrit dans la section Options , l'autre manière est dans la section Opérandes .

Il y a une différence entre -vet passer les affectations à la fin avec les noms de fichiers:

  • Avec -v:

L'application doit s'assurer que l'argument d'assignation est sous la même forme qu'un opérande d'assignation. L'affectation de variable spécifiée doit se produire avant d'exécuter le programme awk, y compris les actions associées aux modèles BEGIN (le cas échéant). Plusieurs occurrences de cette option peuvent être spécifiées.

  • Mélangé avec les noms de fichiers:

[...] Chacune de ces affectations de variables doit avoir lieu juste avant le traitement du fichier suivant , le cas échéant. Ainsi, une affectation avant le premier argument de fichier doit être exécutée après les actions BEGIN (le cas échéant), tandis qu'une affectation après le dernier argument de fichier doit se produire avant les actions END (le cas échéant). S'il n'y a pas d'arguments de fichier, les affectations doivent être exécutées avant de traiter l'entrée standard.

Exemple:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four
Tapis
la source
Hou la la! Cela ajoute quelques points de contrôle intéressants ... c'est forcément utile. Merci ...
Peter.O
1
Mon premier "Wow!" tient toujours, mais il a été quelque peu tempéré en approfondissant la réponse d'Arcege ... Je l'ai testé avec un vrai fichier nommé "var = three" ... a awkdonné la priorité à une affectation variable ... Cela a un corollaire majeur , c'est à dire. Dans tous les cas, lorsqu'un nom de fichier a cette forme, il sera ignoré et la variable sera définie ... Il semble que la seule façon d'éviter ce conflit est de s'assurer que les noms de fichiers pour le répertoire de travail actuel doivent toujours être préfixés avec leur chemin relatif:./var=three
Peter.O
@ Peter.O, oui, c'est aussi l'une des raisons pour lesquelles la -vsyntaxe a été introduite. Vous devriez penser à la -vsyntaxe comme la meilleure façon de faire des affectations à l'avenir.
dubiousjim
@ Peter.O, excellent point sur le "gotcha" si un nom de fichier est une affectation de variable valide. Si vous utilisez une variable shell contenant un nom de fichier et que vous le transmettez comme argument awk, vous pouvez utiliser la capture suivante:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Wildcard
4

Il s'agit d'un ancien style de définition de variables en externe dans awk. C'était ambigu (et si vous aviez un nom de fichier nommé foo=cat), les versions ultérieures ont donc ajouté une -voption. Cela devrait probablement fonctionner pour la compatibilité descendante, mais vous ne pouvez pas garantir. Et comme je l'ai dit, l' -voption est plus récente, donc toutes les versions de awkne la prennent pas en charge.

Arcege
la source
Votre commentaire sur la possibilité d'un conflit de nom de fichier est bon ... Je l'ai testé et c'est certainement un problème. J'ai écrit un peu plus à ce sujet dans un commentaire à la réponse de Mat .. Merci d'avoir mis en évidence ce problème (+1)
Peter.O
2
En fait, comme expliqué dans [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v` et l'affectation des arguments diffèrent lorsqu'ils prennent effet. Est également -vdans POSIX et devrait être présent dans toutes les awkimplémentations sauf la plus ancienne . Utiliser ./ou vous assurer que le nom de fichier contient un caractère non identifiant est probablement le moyen le plus fiable de lever l'ambiguïté.
jw013