Como posso usar variáveis no LHS e RHS de uma substituição de sed?

60

Eu quero fazer:

cat update_via_sed.sh | sed 's/old_name/new_name/' > new_update_via_sed.sh

no meu programa.

Mas quero usar variáveis, por exemplo

old_run='old_name_952'
new_run='old_name_953'

Eu tentei usá-los, mas a substituição não acontece (sem erro). Eu tentei:

cat update_via_sed.sh | sed 's/old_run/new_run/'
cat update_via_sed.sh | sed 's/$old_run/$new_run/'
cat update_via_sed.sh | sed 's/${old_run}/${new_run}/'
    
por Michael Durrant 25.03.2013 / 16:57

11 respostas

20

'in-place' sed (usando a sinalização -i) foi a resposta. Graças a peterph.

sed -i "s@$old@$new@" file
    
por 26.03.2013 / 02:12
41

Você pode fazer:

sed "s/$old_run/$new_run/" < infile > outfile

Mas esteja ciente de que $old_run seria considerado uma expressão regular e, portanto, todos os caracteres especiais contidos na variável, como / ou . , teriam de ser escapou . Da mesma forma, em $new_run , os caracteres & e \ precisariam ser tratados especialmente e você teria que escapar dos caracteres / e newline.

Se o conteúdo de $old_run ou $new_run não estiver sob seu controle, é essencial realizar esse escape ou, de outra forma, esse código equivale a uma vulnerabilidade de injeção de código .

    
por 25.03.2013 / 21:09
30

Isso funcionou:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/'

Como eu quero "reutilizar" o mesmo arquivo, eu realmente uso isso para qualquer um que deseje uma abordagem semelhante:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/' > new_update; mv -f new_update update_via_sed.sh

O acima criado um novo arquivo, em seguida, exclui o arquivo atual do que renomear o novo arquivo para ser o arquivo atual.

    
por 25.03.2013 / 17:01
20

Você pode usar variáveis em sed contanto que seja uma aspa dupla (não uma aspa simples):

sed "s/$var/r_str/g" file_name >new_file

Se você tiver uma barra invertida ( / ) na variável, use um separador diferente, como abaixo

sed "s|$var|r_str|g" file_name >new_file
    
por 07.08.2014 / 17:31
3

man bash informa isso sobre cotação única

Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

Qualquer que seja o tipo que você digitar na linha de comando, o bash o interpreta e envia o resultado para o programa para o qual ele deve ser enviado. Nesse caso, se você usar sed 's/$old_run/$new_run/' , o bash primeiro verá o sed , ele reconhece como um executável presente na variável $PATH . O executável sed requer uma entrada. Bash procura a entrada e encontra 's/$old_run/$new_run/' . Aspas simples dizem que não devemos interpretar o conteúdo e passá-las como estão. Então, o bash os passa para o sed. Sed dá um erro porque $ pode ocorrer apenas no final da linha.

Em vez disso, se usarmos aspas duplas, ou seja, "s/$old_run/$new_run/" , o bash verá isso e interpretará $old_run como um nome de variável e fará uma substituição (essa fase é chamada de expansão de variável). Isso é realmente o que exigimos.

Mas, você tem que ter cuidado ao usar aspas duplas porque, elas são interpretadas primeiro pelo bash e depois dadas ao sed. Então, alguns símbolos como 'devem ser escapados antes de usá-los.

    
por 27.02.2014 / 20:18
1

Correndo o risco de ser descuidado - você considerou perl .

Que - entre outras coisas - é muito bom em fazer operações de "estilo sed", mas também um recurso de programação mais completo.

Parece que no seu exemplo, o que você realmente tenta fazer é incrementar um número.

Então, que tal:

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

while ( <DATA> ) {
    s/old_name_(\d+)/"old_name_".($1+1)/e;
    print;
}

__DATA__
old_name_932

ou como um estilo "liner":

perl -pe 's/old_name_(\d+)/"old_name_".($1+1)/e'
    
por 28.07.2016 / 14:26
1
$ echo $d1 | sed -i 's/zkserver1/'${d1}'/g' deva_file
sed: -e expression #1, char 26: unterminated 's' command 

Em $d1 , estou armazenando valores

Eu não posso substituir o valor da variável, então eu tentei o seguinte comando que está trabalhando

echo $d1 | sed -i 's/zkserver1/'"${d1}"'/g' deva_file

falta de aspas duplas em "${d1}" , esse foi o erro

    
por 20.10.2016 / 13:14
-2

Assumiu que $old_run e $new_run já estão definidos:

cat update_via_sed.sh | eval $(print "sed 's/$old_run/$new_run/g'")

Isso mostra a mudança na tela. Você pode redirecionar a saída para o arquivo, se necessário.

    
por 27.02.2014 / 18:17
-2

Para usar uma variável em sed, use aspas duplas "" para incluir a variável no padrão que você está usando. Por exemplo: a="oi" Se você quiser acrescentar a variável 'a' a um padrão, você pode usar o seguinte: sed -n "1, / padrão" $ {a} "padrão / p" nome do arquivo

    
por 21.07.2017 / 09:03
-2

Você também pode usar o Perl:

perl -pi -e ""s/$val1/$val2/g"" file
    
por 22.06.2018 / 09:09
-2

quebra a string

bad = > linux veja uma string $ old_run:

sed 's/$old_run/$new_run/'

bom = > linux veja uma variável $ old_run:

sed 's/'$old_run'/'$new_run'/'
    
por 12.09.2017 / 00:38

Tags