J'ai trouvé des moyens de transmettre des variables Shell externes à un script awk
, mais je suis confus à propos de '
et "
.
J'ai d'abord essayé avec un script Shell:
$ v=123test
$ echo $v
123test
$ echo "$v"
123test
Puis essayé awk:
$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123
Pourquoi 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.
awk
peut être fait de plusieurs manières. Certains sont meilleurs que d'autres. Cela devrait couvrir la plupart d'entre eux. Si vous avez un commentaire, laissez s'il vous plaît ci-dessous.
Il utilise l'option -v
: (P.S. utilisez un espace après -v
ou il sera moins portable. Par exemple, awk -v var=
et non pas awk -vvar=
)
variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two
Cela 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}'
Attention. Comme l'écrit Ed Morton, les séquences d'échappement seront interprétées de manière à ce que \t
devienne un réel tab
et non \t
si c'est ce que vous recherchez. Peut être résolu en utilisant ENVIRON[]
ou y accéder via ARGV[]
Ici, nous obtenons la variable après le code awk
. Cela fonctionnera correctement 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 d'une variable de cette manière ne fonctionne pas dans le bloc BEGIN
:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
La variable peut également être ajoutée à awk
à l’aide de ici chaîne
awk '{print $0}' <<< "$variable"
test
C'est pareil que:
echo "$variable" | awk '{print $0}'
PS, cela menace la variable en tant qu'entrée de fichier
En écriture TrueY, vous pouvez utiliser la variable ENVIRON
pour imprimer Environmental Variables
Définir une variable avant d'exécuter AWK, vous pouvez l'imprimer comme suit:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["Shell"]}'
MyVar /bin/bash
Comme l'a écrit Steven Penny, vous pouvez utiliser ARGV
pour obtenir le Data Inn à awk.
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
Pour obtenir le fichier de données au code lui-même et pas seulement au début:
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 elle est difficile à lire, et comme le souligne Charles Duffy
, cette version peut également être victime d'une injection de code. Si quelqu'un ajoute des éléments incorrects à la variable, celle-ci sera exécutée dans le code awk
.
Cela fonctionne en extrayant la variable dans le code, de sorte qu’elle en fasse partie.
Si vous voulez créer une awk
qui change de façon dynamique avec l'utilisation de variables, vous pouvez le faire de cette façon, 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 de nombreuses commandes à awk
de cette façon. Même le faire planter avec des commandes non valides.
Utilisation de la citation double
Il est toujours bon de doubler la variable "$variable"
Sinon, plusieurs lignes seront ajoutées en une seule ligne longue.
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 guillemet double:
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 guillemet simple, cela n'augmente pas la valeur de la variable:
awk -v var='$variable' 'BEGIN {print var}'
$variable
Plus d'informations sur AWK et les variables
Lire cette FAQ
Il semble que le bon vieux ENVIRON
awk hash intégré ne soit pas du tout mentionné. Un exemple de son utilisation:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
Utilisez l’un ou l’autre de ces choix en fonction de la manière dont vous souhaitez que les barres obliques inverses soient traitées dans les variables Shell (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 l'option de 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 devrez ajuster ARGC:
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
Je devais insérer la date au début des lignes d'un fichier journal et c'est comme suit
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /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" " $4}'; done