Comment utiliser des variables shell dans un script awk?

j'ai trouvé quelques façons de passer des variables externes à un script awk , mais je suis confus au sujet de ' et " .

tout d'abord, j'ai essayé avec un script shell:

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

alors essayé awk:

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

Quelle est la 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 à ce sujet.

180
demandé sur codeforester 2013-09-29 11:45:03

8 réponses

obtenir des variables shell dans awk peut être fait de plusieurs façons. Certains sont meilleurs que d'autres.


C'est la meilleure façon de le faire. Il utilise l'option -v : (PS.utilisez un espace après -v ou il sera moins portable. Par exemple, awk -v var= not awk -vvar= )

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

cela doit être compatible avec la plupart des awk et la variable est disponible dans le bloc BEGIN ainsi:

variables multiples

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

ici nous obtenons la variable après le code awk . Cela fonctionnera très 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 aussi avec des variables multiples awk '{print a,b,"1519200920"}' a="$var1" b="$var2" file


la Variable peut aussi être ajoutée à awk en utilisant ici chaîne

awk '{print "151930920"}' <<< "$variable"
test

C'est la même chose que:

echo "$variable" | awk '{print "151940920"}'

PS, ce qui menace la variable comme une entrée de fichier


comme L'écrit TrueY, vous pouvez utiliser le ENVIRON pour imprimer Environmental Variables Définir une variable avant de lancer AWK, vous pouvez l'imprimer comme ceci:

X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash

Edit: "c'est l'autre gars" écrire, ce n'est pas la poignée de barre oblique inverse. Pas recommandé.


vous pouvez utiliser une variable à l'intérieur du code awk , mais il est désordonné et difficile à lire, et comme Charles Duffy souligne, cette version peut également être victime d'une injection de code. Si quelqu'un ajoute de mauvaises choses à la variable, elle sera exécutée dans le cadre du code awk .

si vous voulez faire un awk qui change dynamiquement avec l'utilisation de variables, vous pouvez le faire de cette façon, bot ne pas utiliser pour les 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. Même faire planter avec les commandes valides.


il est toujours bon de citer deux fois la variable "$variable"

Si non, plusieurs lignes seront ajoutées comme une seule longue ligne.

exemple:

var="Line one
This is line two"

echo $var
Line one This is line two

echo "$var"
Line one
This is line two

autres erreurs que vous pouvez obtenir sans double citation:

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 un seul devis, il ne développe pas la valeur de la variable:

awk -v var='$variable' 'BEGIN {print var}'
$variable
317
répondu Jotne 2018-05-24 10:10:40

il semble que le bon vieux ENVIRON hachage intégré n'est pas mentionné du tout. Un exemple de son usage:

$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
21
répondu TrueY 2014-11-06 12:46:34

utilisez l'une ou l'autre de ces variables en fonction de la façon dont vous voulez des antislashs dans les variables shell traitées ( avar est une variable awk, svar est une variable shell):

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.

7
répondu Ed Morton 2013-09-29 13:54:14

vous pouvez passer dans l'option de la ligne de commande -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 le rendre plus clair (avec beaucoup moins de v s):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
5
répondu Johnsyweb 2013-09-29 07:57:14

vous pouvez utiliser ARGV:

v=123test
awk 'BEGIN {print ARGV[1]}' "$v"

Notez que si vous allez continuer dans le corps, vous aurez besoin d'ajuster ARGC:

awk 'BEGIN {ARGC--} {print ARGV[2], "151910920"}' file "$v"
3
répondu Steven Penny 2017-01-15 07:05:15

j'ai dû insérer la date au début des lignes d'un fichier journal et c'est fait comme ci-dessous:

DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", "151900920"; }' /path_to_log_file/log_file.log

il peut être redirigé vers un autre fichier pour enregistrer

1
répondu Sina 2016-03-02 08:07:01

je viens de changer la réponse de @Jotne pour"For loop".

for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " }'; done
0
répondu edib 2018-04-10 07:34:20
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
0
répondu Shicheng Guo 2018-07-20 15:13:28