Substituindo padrão por variável

1

Eu tenho 3 linhas de números armazenados em uma variável $new e eu preciso usar isso para substituir 3 linhas de um arquivo que usei grep e armazenado em outra variável $old . Estou tentando sed "s/$old/$new/g" input > output . Mas estou recebendo um erro:

sed: 1: "s/\( 28.47969107 0. ...": unterminated substitute pattern

Meu arquivo de entrada se parece com:

scale
 1.000
primitive lattice vectors
    28.47969107  0.00000000  0.00000000
   0.00000000 28.47969107  0.00000000
   0.00000000  0.00000000 28.47969107
grid dimensions
  100 100 100

Meu $old é as linhas

28.47969107 0.00000000 0.00000000 0.00000000 28.47969107 0.00000000 0.00000000 0.00000000 28.47969107

$new tem o mesmo formato que números antigos, apenas diferentes.

    
por Ajax 19.02.2015 / 00:18

4 respostas

0
sed -e "/$old/i$new" -e "/$old/{N;N;d}" input > output

onde

  • $old pode ser apenas 28.47969107 ou UMA primeira linha 28.47969107 0.00000000 0.00000000
  • $new DEVE estar no formato 28.47969107 0.00000000 0.00000000\n0.00000000 28.47969107 0.00000000\n0.00000000 0.00000000 28.47969107

Outra maneira (se você tiver o novo GNU sed (versão > 4.2.1) com a opção -z ) para escapar do newline dentro dos valores:

sed -z "s/$(printf "%b" "$old"|sed '$!s/$/\/')/$(printf "%b" "$new"|sed 's/$/\/')/" input > output

Ou se você fizer uma substituição dentro da função de atribuição de script

end_esc(){ printf "%b" "$@"|sed '$!s/$/\/' ; }
sed -z "s/$(end_esc $old)/$(end_esc $new)/" input > output
    
por 19.02.2015 / 00:45
0

Primeiro, vamos definir uma string de amostra para new :

$ new=$'1 2 3\n4 5 6\n7 8 9'

Agora, vamos remover as três linhas que seguem primitive lattice vectors e substituí-las por new :

$ awk -v "new=$new" 'f==1{print new} f{f--;next} {print} /primitive/{f=3}' input
scale
 1.000
primitive lattice vectors
1 2 3
4 5 6
7 8 9
grid dimensions
  100 100 100
    
por 19.02.2015 / 01:45
0
sed -e '$!N;$b' -e "/\n.*\n/!N;s/$old/$new/;t" -e P\;D

Os itens acima funcionarão, mas eis a pegadinha: as novas linhas em $old precisam ser representadas como \n e as novas linhas em $new devem ser precedidas por uma barra invertida \ . As novas linhas em seus valores são o que lhe deu problemas. Por exemplo, após a expansão:

sed 's/24.0000000001
.000000000000
.0000000000/...'

... não funciona. Essa é uma expressão regular não terminada - você vê?

Em vez disso:

old='num\nnum\nnum'
new='num\
num\
num'

... é o que você precisa.

Se, por alguma razão, você achar que é complicado escapar das vars por conta própria, então você pode fazer algo como:

(  set -f; IFS='
'; printf '%s\n' / .* '/!N;s/'$old
   printf '%s\\n' */$new"/;t$IFS#"
)| sed -e '$N;$b' -f - -e P\;D input > output

Mas isso dependeria de não haver linhas em branco nas duas variáveis, e provavelmente não é mais fácil.

    
por 19.02.2015 / 14:02
-1

sed s/"$old"/"$new"/g funciona para mim

    
por 19.02.2015 / 09:39

Tags