Variável de ambiente não expandida dentro do argumento da linha de comando

2

Eu tenho um arquivo user-pid.out2 que tem "usernumber" e "process id" como duas colunas. com base no usernumber, quero encontrar o id do processo correspondente. as duas primeiras linhas abaixo não mostram a saída correta, mas quando eu codifico o usuário como 62 na linha 3 & 4 mostra o id do processo correspondente ao usuário 62. Alguém poderia ajudar 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
    
por Anil 17.10.2014 / 09:59

2 respostas

9

O @artm mostrou uma técnica em que você aspas duplas e escape de vários caracteres. Aqui estão 3 outras técnicas

Saia da aspa simples para deixar a casca expandir a variável

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

Passa a variável shell para uma variável awk

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

Se a variável for exportada, use a matriz ENVIRON do awk

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

Esse último deve ser o preferido.

Na primeira abordagem como a do @ artm, o conteúdo da variável shell é embutido dentro do código awk , de modo que se torna uma vulnerabilidade de injeção de comando se o conteúdo da variável não for rigidamente controlado (por exemplo, com USR='blah" || system("reboot") || "' , que chamaria reboot ).

O segundo não introduz uma vulnerabilidade de injeção de comando, mas se $USR contiver caracteres de barra invertida, a variável usr awk não conterá a mesma coisa que a variável $USR shell como awk expande C- como seqüências de escape de barra invertida lá.

Usar ENVIRON não tem nenhum desses problemas.

    
por 17.10.2014 / 12:31
3

o "$USR" no primeiro exemplo não está expandido porque ocorre dentro da sequência com aspas simples '$1 == "$USR" { print $2 }' , portanto, esse código está procurando uma linha com a primeira coluna sendo "$ USR", não 62.

Os seguintes itens devem funcionar:

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

Mudanças:

  1. a linha de comando do awk usa aspas duplas para que $ USR seja expandido
  2. cifrões e caracteres de citação dentro do programa awk são ignorados
  3. $() é usado em vez de backticks, então as barras invertidas são manuseadas corretamente

Observe que, como o valor de USR é interpolado diretamente no script awk, ele só funciona se esse valor contiver caracteres que o awk interpretará literalmente: se $USR contiver \ ou " , todos o inferno vai se soltar - " seria o final do literal da string awk, e \ citaria o próximo caractere.

    
por 17.10.2014 / 10:46