Tengo un archivo user-pid.out2
que 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 awk
có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 $USR
contiene caracteres de barra invertida, la usr
awk
variable no contendrá lo mismo que la $USR
variable de shell, ya que awk
expande secuencias de escape de barra invertida tipo C allí.
El uso ENVIRON
no 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:
- la línea de comando awk usa comillas dobles por lo que $USR se expande
- Los signos de dólar y las comillas dentro del programa awk tienen formato de escape.
$()
se utiliza en lugar de comillas invertidas, por lo quelas barras invertidas se manejan correctamente
Tenga en cuenta que dado que el valor de USR
se interpola directamente en el script awk, solo funciona si ese valor solo contiene caracteres que awk interpretará literalmente: si $USR
contiene \
o "
, se desatará el infierno: "
sería el final de la cadena literal awk. y \
citaría el siguiente personaje.