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.
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
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.
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
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"
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
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
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done