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

bash shell awk


Encontré algunas formas de pasar variables de shell externas a un script awk , pero estoy confundido acerca de ' y " .

Primero,lo intenté con un guión de la concha:

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

Luego intentó torcer:

$ 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 con esto.





Answer 1 Jotne


Obtener variables de shell en awk

Se puede hacer de varias maneras. Algunos son mejores que otros. Esto debería cubrir la mayoría de ellos. Si tienes un comentario, déjalo a continuación. v1.5


Usando -v (La mejor manera, más portátil)

Use 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 :

Si tienes múltiples variables:

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

Advertencia . Como escribe Ed Morton, las secuencias de escape se interpretarán de modo que \t convierta en una tab real y no \t si eso es lo que busca. Puede resolverse utilizando ENVIRON[] o acceder a través de ARGV[]

PD Si te gustan tres barras verticales como separador ||| , no se puede escapar, así que use -F"[|][|][|]"

Ejemplo sobre cómo 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 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
  • Añadiendo múltiples variables:

awk '{print a,b,$0}' a="$var1" b="$var2" file

  • De esta manera, también podemos establecer diferentes separadores de campo FS para cada archivo.

awk 'some code' FS=',' file1.txt FS=';' file2.ext

  • La variable después del bloque de código no funcionará para el bloque BEGIN :

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


Here-string

La variable también se puede agregar a awk usando una cadena aquí de shells que los admiten (incluido Bash):

awk '{print $0}' <<< "$variable"
test

Esto es lo mismo que:

printf '%s' "$variable" | awk '{print $0}'

P.D.esto trata la variable como una entrada de archivo.


ENVIRON entrada

Como TrueY escribe, puede usar ENVIRON para imprimir Variables de entorno . Al configurar una variable antes de ejecutar AWK, puede imprimirla así:

X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash

ARGV Entrada ARGV

Como escribe Steven Penny, puede usar ARGV para obtener los datos en awk:

v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data

Para meter los datos en el código en sí,no sólo en el COMIENZO:

v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test

Variable dentro del código:USAR CON PRECAUCIÓN

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 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 .

Esto funciona extrayendo la variable dentro del código,para que se convierta en parte de él.

Si desea hacer un awk que cambie dinámicamente con el uso de variables, puede hacerlo de esta manera, pero 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 a awk de esta manera. Incluso haz que se bloquee con comandos no válidos.


Información extra:

Uso de la doble cita

Siempre es bueno comilla doble variable "$variable"
Si no,se añadirán varias líneas como una sola línea larga.

Example:

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 se pueden obtener sin doble cita:

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 una sola cita,no expande el valor de la variable:

awk -v var='$variable' 'BEGIN {print var}'
$variable

Más información sobre el AWK y las variables

Lee este faq .




Answer 2 TrueY


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



Answer 3 Ed Morton


Utilice cualquiera de estos según cómo desee barras invertidas 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.




Answer 4 Johnsyweb


Puede pasar la opción de línea de comando -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 muchos menos v s):

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



Answer 5 Steven Penny


Puede utilizar el ARGV:

v=123test
awk 'BEGIN {print ARGV[1]}' "$v"

Tenga en cuenta que si va a continuar en el cuerpo,tendrá que ajustar el ARGC:

awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"