Substituição de variables ​​de ambiente em sed

Se eu executar esses comandos a partir de um script:

#my.sh PWD=bla sed 's/xxx/'$PWD'/' ... $ ./my.sh xxx bla 

está bem.

Mas, se eu correr:

 #my.sh sed 's/xxx/'$PWD'/' ... $ ./my.sh $ sed: -e expression #1, char 8: Unknown option to `s' 

Eu li em tutoriais que para replace variables ​​de ambiente do shell você precisa parar, e ‘fora citar’ a parte $varname para que não seja substituído diretamente, que é o que eu fiz, e que funciona somente se a variável for definida imediatamente antes .

Como posso obter o sed para reconhecer um $var como uma variável de ambiente como é definido no shell?

   

Seus dois exemplos parecem idênticos, o que dificulta o diagnóstico de problemas. Problemas potenciais:

  1. Você pode precisar de aspas duplas, como em sed 's/xxx/'"$PWD"'/'

  2. $PWD pode conter uma barra, caso em que você precisa encontrar um caractere não contido em $PWD para usar como um delimitador.

Para pregar ambos os problemas de uma só vez, talvez

 sed 's@xxx@'"$PWD"'@' 

Além da resposta de Norman Ramsey, gostaria de acrescentar que você pode citar duas vezes a string inteira (o que pode tornar a declaração mais legível e menos propensa a erros).

Então, se você quiser procurar por ‘foo’ e substituí-lo pelo conteúdo de $ BAR, você pode colocar o comando sed entre aspas duplas.

 sed 's/foo/$BAR/g' sed "s/foo/$BAR/g" 

No primeiro, $ BAR não expandirá corretamente, enquanto no segundo $ BAR irá expandir corretamente.

Você pode usar outros caracteres além de “/” em substituição:

 sed "s#$1#$2#g" -i FILE 

Outra alternativa fácil:

Como $PWD geralmente contém uma barra / , use | em vez de / para a declaração sed:

 sed -e "s|xxx|$PWD|" 

Com a sua edição, vejo o seu problema. Digamos que o diretório atual seja /home/yourname … neste caso, seu comando abaixo:

 sed 's/xxx/'$PWD'/' 

será expandido para

 sed `s/xxx//home/yourname// 

o que não é válido. Você precisa colocar um caractere \ na frente de cada / em seu $ PWD se você quiser fazer isso.

 VAR=8675309 echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\ sed 's/:[0-9]*:/:'$VAR':/1' 

onde VAR contém o que você deseja replace o campo com

Na verdade, a coisa mais simples (pelo menos no gnu) é usar um separador diferente para o comando de substituição (s) do sed. Então, em vez de s / pattern / ‘$ mypath’ / sendo expandido para s / pattern // meu / path / o que obviamente irá confundir o comando s, use s! Pattern! ‘$ Mypath’! que será expandido para s! pattern! / my / path! Eu usei o caractere bang (!) (Ou use qualquer coisa que você quiser) que evita a barra normal, mas não a única, como separador.

caminho ruim: altere o delimitador

 sed 's/xxx/'"$PWD"'/' sed 's:xxx:'"$PWD"':' sed 's@xxx@'"$PWD"'@' 

talvez aqueles que não são a resposta final,

você não pode saber qual caractere irá ocorrer em $PWD , / : OR @ .

O bom caminho é replace o caractere especial em $PWD .

boa maneira: escape delimitador

por exemplo:

use / como delimitador

 echo ${url//\//\\/} x.com:80\/aa\/bb\/aa.js echo ${url//\//\/} https://stackoverflow.com/questions/584894/environment-variable-substitution-in-sed/x.com:80/aa/bb/aa.js echo "${url//\//\/}" x.com:80\/aa\/bb\/aa.js echo $tmp | sed "s/URL/${url//\//\\/}/" URL echo $tmp | sed "s/URL/${url//\//\/}/" URL 

OU

use : como delimitador (mais legível que / )

 echo ${url//:/\:} https://stackoverflow.com/questions/584894/environment-variable-substitution-in-sed/x.com:80/aa/bb/aa.js echo "${url//:/\:}" x.com\:80/aa/bb/aa.js echo $tmp | sed "s:URL:${url//:/\:}:g" https://stackoverflow.com/questions/584894/environment-variable-substitution-in-sed/x.com:80/aa/bb/aa.js 

Lidando com VARIÁVEIS dentro de sed

 [root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt [root@gislab00207 ldom]# cat /tmp/1.txt domainname: None [root@gislab00207 ldom]# echo ${DOMAIN_NAME} dcsw-79-98vm.us.oracle.com [root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g' --- Below is the result -- very funny. domainname: ${DOMAIN_NAME} --- You need to single quote your variable like this ... [root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g' --- The right result is below domainname: dcsw-79-98vm.us.oracle.com 

Eu tive problema semelhante, eu tinha uma lista e eu tenho que construir um script SQL baseado em template (que continha @INPUT@ como elemento para replace):

 for i in LIST do awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output done