J'ai trouvé des moyens de transmettre des variables externes de l'interpréteur de commandes à un script awk
, mais je ne comprends pas bien les termes ''`` et
"'``.
J'ai d'abord essayé avec un script shell :
$ v=123test
$ echo $v
123test
$ echo "$v"
123test
Puis j'ai essayé avec awk :
$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123
Pourquoi cette différence ?
Enfin, j'ai essayé ceci :
$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string
Je suis confus à propos de ça.
Transférer les variables de l'interpréteur de commandes dans
awk
.peut être fait de plusieurs façons. Certaines sont meilleures que d'autres. Ceci devrait couvrir la plupart d'entre elles. Si vous avez un commentaire, veuillez le laisser ci-dessous.
-v
(La meilleure façon, la plus portable)Utilisez l'option -v
: (P.S. utilisez un espace après -v
ou cela sera moins portable. Par exemple, awk -v var=
et non awk -vvar=
)
variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two
Ceci devrait être compatible avec la plupart des awk
, et la variable est également disponible dans le bloc BEGIN
:
Si vous avez plusieurs variables :
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
Avertissement. Comme l'écrit Ed Morton, les séquences d'échappement seront interprétées de sorte que \t
devient un vrai tab
et non \t
si c'est ce que vous recherchez. Peut être résolu en utilisant ENVIRON[]
ou en y accédant via ARGV[]
.
PS Si vous aimez les trois barres verticales comme séparateur |||
, elles ne peuvent pas être échappées, alors utilisez -F" ;[|][|][|]"
.
Exemple de récupération de données d'un programme ou d'une fonction dans
awk
(ici la date est utilisée)
awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'
Ici, nous obtenons la variable après le code awk
. Cela fonctionne bien tant que vous n'avez pas besoin de la variable dans le bloc BEGIN
:
variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
Cela fonctionne également avec plusieurs variables
awk '{print a,b,$0}' ; a="$var1" ; b="$var2" ; file
L'utilisation de variables de cette façon ne fonctionne pas dans le bloc BEGIN
:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
Une variable peut également être ajoutée à awk
en utilisant une [here-string][1] à partir des shells qui les supportent (y compris Bash) :
awk '{print $0}' <<< "$variable"
test
C'est la même chose que :
printf '%s' "$variable" | awk '{print $0}'
P.S. ceci traite la variable comme une entrée de fichier.
Comme l'écrit TrueY, vous pouvez utiliser le ENVIRON
pour imprimer des variables d'environnement.
En définissant une variable avant de lancer AWK, vous pouvez l'imprimer comme ceci :
X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
Comme l'écrit Steven Penny, vous pouvez utiliser ARGV
pour obtenir les données dans awk :
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
Pour obtenir les données dans le code lui-même, pas seulement dans le BEGIN :
v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test
Vous pouvez utiliser une variable dans le code awk
, mais c'est désordonné et difficile à lire, et comme Charles Duffy
le fait remarquer, cette version peut aussi être victime d'injection de code. Si quelqu'un ajoute de mauvaises choses à la variable, elles seront exécutées dans le cadre du code awk
.
Cela fonctionne en extrayant la variable à l'intérieur du code, de sorte qu'elle en devienne une partie intégrante.
Si vous voulez faire un awk
qui change dynamiquement avec l'utilisation de variables, vous pouvez le faire de cette façon, mais NE l'utilisez PAS pour des variables normales.
variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
Voici un exemple d'injection de code :
variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000
Vous pouvez ajouter beaucoup de commandes à awk
de cette façon. Et même le faire planter avec des commandes non valides.
Il est toujours bon de citer deux fois la variable "$variable"
.
Sinon, plusieurs lignes seront ajoutées comme une longue ligne unique.
Exemple :
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
D'autres erreurs peuvent être obtenues sans guillemets :
variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ syntax error
Et avec le guillemet simple, il ne développe pas la valeur de la variable :
awk -v var='$variable' 'BEGIN {print var}'
$variable
[Lire cette faq][2].
[1] : http://en.wikipedia.org/wiki/Here_document [2] : http://cfajohnson.com/shell/cus-faq-2.html#Q24
Utilisez l'un ou l'autre selon la façon dont vous voulez que les backslashes dans les variables de l'interpréteur de commandes soient gérés (avar
est une variable awk, svar
est une variable de l'interpréteur de commandes) :
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
Voir http://cfajohnson.com/shell/cus-faq-2.html#Q24 pour plus de détails et d'autres options. La première méthode ci-dessus est presque toujours votre meilleure option et a la sémantique la plus évidente.
Vous pouvez passer l'[option de ligne de commande][1] -v
avec un nom de variable (v
) et une valeur (=
) de la variable d'environnement ("${v}"
) :
% awk -vv="${v}" 'BEGIN { print v }'
123test
Ou pour être plus clair (avec beaucoup moins de v
s) :
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
[1] : http://www.gnu.org/software/gawk/manual/gawk.html#Options