Como usar uma variável de shell dentro do comando do sed? [duplicado]

4
    

Esta pergunta já tem uma resposta aqui:

    

sabemos que podemos obter o valor de uma variável usando o sinal $:

x=3
echo $x
3

Existem outras maneiras que podemos usar para obter o valor sem usar $ sign.

Estou perguntando porque $ sign é um caractere especial para sed e recebo sed: -e expression #1, char 31: unterminated s' command error ao tentar fazer isso:

A=25 #lineNumber
destStr="192.168.1.3 192.168.1.4"
sed ""$A"s/Allow from .*/Allow from $destStr/" -i test2

e imprime a string destStr (não o valor) quando eu uso o caractere de escape \ :

sed ""$A"s/Allow from .*/Allow from \$destStr/" -i test2

usando echo em vez de sed :

25s/Allow from .*/Allow from  192.168.1.3
192.168.1.4
/ -i test2
    
por Networker 07.08.2014 / 14:12

5 respostas

5

Como as edições finais foram reveladas, o problema não está relacionado ao cifrão, mas é causado pelo conteúdo de deststr , que não é 192.168.1.3 192.168.1.4 , mas sim duas linhas, uma contendo apenas 192.168.1.3 e a outra contendo apenas 192.168.1.4 , ambas as linhas terminadas com um caractere de nova linha. Ou seja, o comando real após a substituição da variável é:

sed "25s/Allow from .*/Allow from  192.168.1.3
192.168.1.4
/" -i test2

Agora, sed interpreta seu comando linha por linha e, assim, o primeiro comando que ele tenta interpretar é:

25s/Allow from .*/Allow from  192.168.1.3

que claramente é um comando s não finalizado e, portanto, relatado por sed como tal.

Agora, a solução que você encontrou, usando echo , funciona porque

echo $var

chama echo com dois argumentos (porque o espaço em branco não é citado, é interpretado como delimitador de argumentos), sendo o primeiro 192.168.1.3 e o segundo 192.168.1.4 ; ambos são formulários que não são interpretados pela shell.

Agora, echo apenas exibe seus argumentos (não-opcionais) separados por um espaço, portanto você agora obtém como linha de comando:

sed "25s/Allow from .*/Allow from  192.168.1.3 192.168.1.4/" -i test2

como pretendido.

Note, porém, que para a substituição de comandos, em vez de backticks, você deve usar $() sempre que possível, pois é muito fácil errar os backticks. Portanto, o seguinte faz o que você quer:

sed "$A s/Allow from .*/Allow from $(echo $destStr)/" -i test2

Note que eu também aproveitei o fato de que sed permite um espaço entre endereço e comando, para simplificar as citações. Em situações em que esse espaço extra não é possível, você também pode usar a seguinte sintaxe:

sed "${A}s/Allow from .*/Allow from $(echo $destStr)/" -i test2

Observe também que isso se baseia no fato de que os caracteres não espaciais em destStr não são interpretados nem pelo shell, nem pelo sed se ocorrer na string de substituição.

    
por 07.08.2014 / 15:16
3

Consegui resolver meu problema usando echo com '':

sed ""$A"s/Allow from .*/Allow from 'echo $destStr'/" -i test2

mas ainda quero saber se existem outras maneiras de obter o valor sem usar $ sign.

    
por 07.08.2014 / 14:22
2

É assim que você pode fazer isso no script:

sed -e "${A}s/Allow from .*/Allow from ${destStr}/" -i test2

Usando ${variable} , deixe o bash interpretar ${variable}s/... como você deseja.

    
por 07.08.2014 / 14:33
1

Tentando responder a pergunta: "Há outras maneiras de usar o valor sem usar $ sign."

Isso não está no contexto do seu caso de uso, mas você pode fazer algo assim:

$SOME_VAR="some value or something"
f() { echo ${!1}; }
some_command 'f "SOME_VAR"'

Você poderia usar isso para evitar usar $ na lista de argumentos para sed.

    
por 07.08.2014 / 19:26
0

E sobre

sed $A's/Allow from .*/Allow from '$destStr'/' -i test2

assumindo destStr não tem branco.

ou

echo $A"s/Allow from .*/Allow from $destStr/" | sed -f - -i test2

o segundo formulário permite branco.

    
por 07.08.2014 / 14:18