Encontré algunas maneras de pasar variables de shell externas a un script awk
, pero estoy confundido acerca de '
y "
.
Primero, lo intenté con un script de shell:
$ v=123test $ echo $v 123test $ echo "$v" 123test
Luego intenté awk:
$ awk 'BEGIN{print "'$v'"}' $ 123test $ awk 'BEGIN{print '"$v"'}' $ 123
¿Por qué es la diferencia?
Por último, probé esto:
$ 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
Estoy confundido acerca de esto.
Obtener variables de shell en awk
se puede hacer de varias maneras. Algunos son mejores que otros.
Esta es la mejor manera de hacerlo. Utiliza la opción -v
: (PS usa un espacio después de -v
o será menos portátil. Por ejemplo, awk -v var=
not awk -vvar=
)
variable="line one\nline two" awk -v var="$variable" 'BEGIN {print var}' line one line two
Esto debería ser compatible con la mayoría de awk
y la variable también está disponible en el bloque BEGIN
:
Múltiples variables
awk -va="$var1" -vb="$var2" 'BEGIN {print a,b}'
Aquí obtenemos la variable después del código awk
. Esto funcionará bien siempre que no necesite la variable en el bloque BEGIN
:
variable="line one\nline two" echo "input data" | awk '{print var}' var="$variable" or awk '{print var}' var="$variable" file
Esto también funciona con múltiples variables awk '{print a,b,$0}' a="$var1" b="$var2" file
La variable también se puede agregar a awk
usando aquí la cadena
awk '{print $0}' < << "$variable" test
Esto es lo mismo que:
echo "$variable" | awk '{print $0}'
PD, esto amenaza la variable como una entrada de archivo
Como TrueY write, puede usar ENVIRON
para imprimir Environmental Variables
Configurando una variable antes de ejecutar AWK, puede imprimirlo así:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}' MyVar /bin/bash
Editar: como escribe "ese otro tipo", esto no maneja la barra diagonal inversa. No recomendado.
Puede usar una variable dentro del código awk
, pero es complicado y difícil de leer, y como señala Charles Duffy
, esta versión también puede ser una víctima de la inyección de código. Si alguien agrega cosas malas a la variable, se ejecutará como parte del código awk
.
Si quiere hacer un awk
que cambie dinámicamente con el uso de variables, puede hacerlo de esta manera, bot NO lo use para variables normales.
variable="line one\nline two" awk 'BEGIN {print "'"$variable"'"}' line one line two
Aquí hay un ejemplo de inyección de código:
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
Puede agregar muchos comandos para awk
esta manera. Incluso hágalo fallar con comandos no válidos.
Siempre es bueno duplicar la variable de cotización "$variable"
De lo contrario, se agregarán varias líneas como una sola línea larga.
Ejemplo:
var="Line one This is line two" echo $var Line one This is line two echo "$var" Line one This is line two
Otros errores que puede obtener sin comillas dobles:
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
Y con comillas simples, no expande el valor de la variable:
awk -v var='$variable' 'BEGIN {print var}' $variable
Parece que el viejo hash incorporado ENVIRON
awk no se menciona en absoluto. Un ejemplo de su uso:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}' Solaris rxvt
Utilice cualquiera de estos dependiendo de cómo quiera las barras diagonales inversas en las variables de shell manejadas ( avar
es una variable awk, svar
es una variable de shell):
awk -v avar="$svar" '... avar ...' file awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
Consulte http://cfajohnson.com/shell/cus-faq-2.html#Q24 para obtener detalles y otras opciones. El primer método anterior es casi siempre su mejor opción y tiene la semántica más obvia.
Podría pasar la opción de línea de comandos -v
con un nombre de variable ( v
) y un valor ( =
) de la variable de entorno ( "${v}"
):
% awk -vv="${v}" 'BEGIN { print v }' 123test
O para hacerlo más claro (con mucho menos v
s):
% environment_variable=123test % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }' 123test
Puede utilizar ARGV:
v=123test awk 'BEGIN {print ARGV[1]}' "$v"
Tenga en cuenta que si va a continuar en el cuerpo, deberá ajustar ARGC:
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
Tuve que insertar la fecha al comienzo de las líneas de un archivo de registro y se hace como a continuación:
DATE=$(date +"%Y-%m-%d") awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
Se puede redirigir a otro archivo para guardar
Acabo de cambiar la respuesta de @ Jotne por “for loop”.
for i in `seq 11 20`; do host myserver-$i | awk -vi="$i" '{print "myserver-"i" " $4}'; done
for i in chr{1..22} chrX chrY do awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed echo $i done