Ho trovato alcuni modi per passare variabili esterne Shell a uno script awk
, ma sono confuso su '
e "
.
Per prima cosa, ho provato con uno script Shell:
$ v=123test
$ echo $v
123test
$ echo "$v"
123test
Quindi ho provato awk:
$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123
Perché la differenza?
Infine ho provato questo:
$ 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
Sono confuso su questo.
awk
può essere fatto in diversi modi. Alcuni sono migliori di altri. Questo dovrebbe riguardare la maggior parte di loro. Se hai un commento, per favore, lascia qui sotto.
Usa l'opzione -v
: (P.S. usa uno spazio dopo -v
o sarà meno portabile.E., awk -v var=
not awk -vvar=
)
variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two
Questo dovrebbe essere compatibile con la maggior parte di awk
e la variabile è disponibile anche nel blocco BEGIN
:
Se hai più variabili:
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
Avvertimento. Come scrive Ed Morton, le sequenze di escape verranno interpretate in modo che \t
diventi un tab
reale e non \t
se questo è ciò che si cerca. Può essere risolto utilizzando ENVIRON[]
o accedendolo tramite ARGV[]
Qui otteniamo la variabile dopo il codice awk
. Funzionerà bene finché non avrai bisogno della variabile nel blocco BEGIN
:
variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
Funziona anche con più variabili awk '{print a,b,$0}' a="$var1" b="$var2" file
L'uso della variabile in questo modo non funziona nel blocco BEGIN
:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
La variabile può anche essere aggiunta a awk
usando here string
awk '{print $0}' <<< "$variable"
test
Questo è lo stesso di:
echo "$variable" | awk '{print $0}'
PS, questo minaccia la variabile come input di file
Come TrueY write, puoi usare ENVIRON
per stampare Environmental Variables
Impostando una variabile prima di eseguire AWK, puoi stamparla in questo modo:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["Shell"]}'
MyVar /bin/bash
Come scrive Steven Penny, puoi usare ARGV
per fare in modo che la raccolta di dati funzioni.
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
Per ottenere il data inn per il codice stesso non solo l'INIZIO:
v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test
Puoi usare una variabile all'interno del codice awk
, ma è disordinata e difficile da leggere e, come sottolinea Charles Duffy
, questa versione potrebbe anche essere vittima dell'iniezione di codice. Se qualcuno aggiunge cose cattive alla variabile, verrà eseguito come parte del codice awk
.
Funziona estraendo la variabile all'interno del codice, quindi diventa parte di esso.
Se vuoi creare un awk
che cambia dinamicamente con l'uso di variabili, puoi farlo in questo modo, bot NON usarlo per le variabili normali.
variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
Ecco un esempio di iniezione di codice:
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
È possibile aggiungere molti comandi a awk
in questo modo. Anche farlo schiantare con comandi non validi.
Uso della doppia citazione
È sempre bene raddoppiare la variabile "$variable"
In caso contrario, verranno aggiunte più righe come una lunga linea singola.
Esempio:
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
Altri errori che puoi ottenere senza virgolette doppie:
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
E con virgolette singole, non espande il valore della variabile:
awk -v var='$variable' 'BEGIN {print var}'
$variable
Ulteriori informazioni su AWK e variabili
Leggi questa FAQ
Sembra che il buon vecchio ENVIRON
awk hash built-in non sia menzionato affatto. Un esempio del suo utilizzo:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
Usa una di queste opzioni a seconda di come vuoi gestire i backslash nelle variabili Shell (avar
è una variabile awk, svar
è una variabile Shell):
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
Vedi http://cfajohnson.com/Shell/cus-faq-2.html#Q24 per dettagli e altre opzioni. Il primo metodo sopra è quasi sempre la tua migliore opzione e ha la semantica più ovvia.
È possibile passare l'opzione command-line-v
con un nome di variabile (v
) e un valore (=
) della variabile di ambiente ("${v}"
):
% awk -vv="${v}" 'BEGIN { print v }'
123test
O per renderlo più chiaro (con molto meno v
s):
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
Puoi utilizzare ARGV:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
Nota che se hai intenzione di continuare nel corpo, dovrai regolare 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
Ho dovuto inserire la data all'inizio delle righe di un file di registro ed è fatta come di seguito:
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
Può essere reindirizzato a un altro file da salvare
Ho appena cambiato la risposta di @ Jotne per "for loop".
for i in `seq 11 20`; do Host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done