Usando sed para expandir variáveis ??de ambiente dentro de arquivos
-
05-07-2019 - |
Pergunta
Eu gostaria de usar Sed para expandir variáveis ??dentro de um arquivo.
Suponha que eu exportados uma variável VARIÁVEL = alguma coisa, e ter um arquivo de "teste" com o seguinte:
I'd like to expand this: "${VARIABLE}"
Eu tenho tentado comandos como o seguinte, mas sem sucesso:
cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile
O resultado é o "outputfile" com a variável ainda não expandido:
I'd like to expand this: "${VARIABLE}"
Ainda assim, correndo eval "echo '${VARIABLE}'
em bash resultados do console no valor "algo" que está sendo ecoado. Além disso, eu testado e esse padrão é trully sendo correspondida.
A saída desejada seria
I'd like to expand this: "something"
Alguém pode lançar uma luz sobre isso?
Solução
Considere a sua versão de teste:
cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile
A razão isso não funcionar é porque requer presciência por parte do shell. O script sed é gerado antes de qualquer padrão é acompanhado por sed, para que o shell não pode fazer esse trabalho para você.
Eu fiz isso de duas maneiras no passado. Normalmente, eu tive uma lista de variáveis ??conhecidas e seus valores, e eu fiz a substituição dessa lista:
for var in PATH VARIABLE USERNAME
do
echo 's%${'"$var"'}%'$(eval echo "\$$var")'%g'
done > sed.script
cat test | sed -f sed.script > outputfile
Se você deseja mapear variáveis ??arbitrariamente, então você quer necessidade de lidar com todo o ambiente (em vez de uma lista fixa de nomes de variáveis, use a saída do env
, devidamente editado), ou usar Perl ou Python vez.
Note que, se o valor de uma variável de ambiente contém uma barra na sua versão, você executar em problemas usando a barra como separador de campo no s /// notação. Eu usei o '%' desde relativamente poucas variáveis ??de ambiente usar isso - mas há alguns encontrados em algumas máquinas que contêm '% dos personagens e assim uma solução completa é mais complicado. Você também precisa se preocupar com barras invertidas no valor. Você provavelmente tem que usar algo como '$(eval echo "\$$var" | sed 's/[\%]/\\&/g')
' para escapar as barras invertidas e símbolos por cento no valor da variável de ambiente. rugas final: algumas versões do sed
tem (ou teve) uma capacidade limitada para o tamanho do roteiro - versões mais antigas do HP-UX tinha um limite de cerca de 100. Eu não tenho certeza se isso ainda é um problema, mas como foi recentemente como há 5 anos.
A adaptação simplória do script original lê:
env |
sed 's/=.*//' |
while read var
do
echo 's%${'"$var"'}%'$(eval echo "\$$var" | sed 's/[\%]/\\&/g')'%g'
done > sed.script
cat test | sed -f sed.script > outputfile
No entanto, a melhor solução usa o fato de que você já tem os valores na saída do env
, então podemos escrever:
env |
sed 's/[\%]/\\&/g;s/\([^=]*\)=\(.*\)/s%${\1}%\2%/' > sed.script
cat test | sed -f sed.script > outputfile
Esta é completamente seguro porque o shell não avalia qualquer coisa que não deve ser avaliada - você tem que ser tão cuidadosos com metacaracteres shell em valores variáveis. Esta versão só pode eventualmente topar com algum problema, se alguma saída de env
é mal formado, eu acho.
Cuidado -. Escrever scripts sed
com sed
é uma ocupação esotérico, mas que ilustra o poder de boas ferramentas
Todos estes exemplos são negligentes em não limpar o arquivo temporário (s).
Outras dicas
Talvez você pode obter perto sem usar sed:
$ echo $VARIABLE
something
$ cat test
I'd like to expand this: ${VARIABLE}
$ eval "echo \"`cat test`\"" > outputfile
$ cat outputfile
I'd like to expand this: something
Vamos variável shell interpolação fazer o trabalho.