¿Cómo utilizo las variables del shell en un script awk?

He encontrado algunas formas de pasar variables externas del shell a un script awk, pero estoy confundido sobre ' y ".

Primero, intenté con un script de shell:

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

Luego probé con awk:

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

¿A qué se debe la diferencia?

Por último, he probado 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 con esto.

Solución

Obtener variables del shell en awk. puede hacerse de varias maneras. Algunas son mejores que otras. Esto debería cubrir la mayoría de ellas. Si tienes algún comentario, por favor déjalo abajo.


Usando -v (La mejor manera, la más portable)

Utilice la opción -v: (P.D. utilice un espacio después de -v o será menos portable. Por ejemplo, awk -v var= no 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 los awk, y la variable está disponible en el bloque BEGIN también:

Si tiene varias variables:

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

Atención. Como escribe Ed Morton, las secuencias de escape serán interpretadas de modo que \t se convierte en una tab real y no en \t si eso es lo que se busca. Se puede solucionar utilizando ENVIRON[] o accediendo a través de ARGV[].

PS Si le gustan las tres barras verticales como separador |||, no se puede escapar, así que use -F"[|][|][|]".

Ejemplo para obtener datos de un programa/función inn a awk (aquí se usa la fecha)

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

Variable después del bloque de código

Aquí obtenemos la variable después del código awk. Esto funcionará bien siempre que no necesites 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

El uso de la variable de esta manera no funciona en el bloque BEGIN:

echo "input data" | awk 'BEGIN {print var}' var="${variable}"

Here-string

También se puede añadir una variable a awk utilizando una [here-string][1] desde los shells que las soportan (incluyendo Bash):


awk '{print $0}' 
Comentarios (6)

Utiliza cualquiera de ellas dependiendo de cómo quieras que se manejen las barras invertidas en las variables del shell (avar es una variable awk, svar es una variable del shell):

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

Ver http://cfajohnson.com/shell/cus-faq-2.html#Q24 para más detalles y otras opciones. El primer método anterior es casi siempre su mejor opción y tiene la semántica más obvia.

Comentarios (0)

Puede 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 muchas menos v):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
Comentarios (0)