Variable de entorno no expandida dentro del argumento de la línea de comando

Variable de entorno no expandida dentro del argumento de la línea de comando

Tengo un archivo user-pid.out2que tiene "número de usuario" e "id de proceso" en dos columnas. Según el número de usuario, quiero encontrar la identificación del proceso correspondiente. Las primeras dos líneas a continuación no muestran el resultado correcto, pero cuando codifico al usuario como 62 en las líneas 3 y 4, muestra la identificación del proceso correspondiente al usuario 62. ¿Podría alguien ayudarme, por favor?

USR=62
usrpid=`awk '$1 == "$USR" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo "first:" $USR $usrpid
# This shows 62 and blank for process id

usrpid=`awk '$1 == "62" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo  "second:" $USR $usrpid
# This shows 62 and process id corresponding to this user in the file user-pid.out2

Respuesta1

@artm mostró una técnica en la que se utilizan comillas dobles en el script awk y se escapan varios caracteres. Aquí hay otras 3 técnicas.

Salga de la comilla simple para permitir que el shell expanda la variable

usrpid=$(awk '$1 == "'"$USR"'" {print $2}' file)

Pasar la variable de shell a una variable awk

usrpid=$(awk -v usr="$USR" '$1 == usr {print $2}' file)

Si la variable se exporta, use la matriz ENVIRON de awk

usrpid=$(awk '$1 == ENVIRON["USR"] {print $2}' file)

Este último debería ser el preferido.

En el primer enfoque, como el de @artm, el contenido de la variable de shell está incrustado dentro del awkcódigo, por lo que se convierte en unvulnerabilidad de inyección de comandosi el contenido de la variable no está estrictamente controlado (por ejemplo, con USR='blah" || system("reboot") || "', eso llamaría reboot).

El segundo no introduce una vulnerabilidad de inyección de comandos, pero si $USRcontiene caracteres de barra invertida, la usr awkvariable no contendrá lo mismo que la $USRvariable de shell, ya que awkexpande secuencias de escape de barra invertida tipo C allí.

El uso ENVIRONno tiene ninguno de esos problemas.

Respuesta2

en "$USR"el primer ejemplo no se expande porque ocurre dentro de la cadena entre comillas simples '$1 == "$USR" { print $2 }', por lo que este código busca una fila cuya primera columna sea "$USR", no 62.

Lo siguiente debería funcionar:

usrpid=$(awk "\$1 == \"$USR\" {print \$2}" /home/hu/batchhu/dbscripts_tst2/user-pid.out2)

Cambios:

  1. la línea de comando awk usa comillas dobles por lo que $USR se expande
  2. Los signos de dólar y las comillas dentro del programa awk tienen formato de escape.
  3. $()se utiliza en lugar de comillas invertidas, por lo quelas barras invertidas se manejan correctamente

Tenga en cuenta que dado que el valor de USRse interpola directamente en el script awk, solo funciona si ese valor solo contiene caracteres que awk interpretará literalmente: si $USRcontiene \o ", se desatará el infierno:  "sería el final de la cadena literal awk. y \citaría el siguiente personaje.

información relacionada