Shell script pesquisar e substituir o texto de duas linhas?

preciso pesquisar o conteúdo de duas linhas e para fazer uma substituição, mas o comando sed não está aceitando quebra de linha na string a ser consultada. Como fazer isso?

Amostra arquivo ‘alvo’:

         width="117.99999"
         id="rect3925-61"
         style="fill:#ffe35f;fill-opacity:1;

Estou tentando assim, mas não funciona:

id="rect3925-61"
color_1="ffe35f"
color_2="@@@@@@"

before="id=\"$id\"\n         style=\"fill:#$color_1;"

after="id=\"$id\"\n         style=\"fill:#$color_2;"

sed -i "s/$before/$after/g" "$PWD/alvo"

Exemplo: Preciso pesquisar por essa string:

id="rect3925-61"
         style="fill:#ffe35f;

para substituir por essa:

id="rect3925-61"
         style="fill:#@@@@@@;

Apesar do sed não aceitar quebra de linha, há n para avançar uma linha e { } para agrupar comandos.

Assim, a solução é buscar por rect3925-61 e, ao encontrá-lo, avançar uma linha e fazer a substituição.

sed "/$id/ { n; s/$color_1/$color_2/g }" alvo

(vale lembrar que $PWD/alvo é redundante. Sem especificar o caminho completo, os arquivos são tratados em relação ao diretório atual).


Outra opção é usar a opção -z do sed, que torna caracteres nulos (NUL) os delimitadores “impermeáveis” de strings a serem consultadas, permitindo assim a consulta de strings com quebras de linha (permitindo até seu script funcionar sem alteração).

3 curtidas

Uma curiosidade, existe alguma forma de buscar pelo $id e retornar uma linha para fazer a substituição?

width="117.99999"
         style="fill:#ffe35f;
id="rect3925-61"

O sed, assim como o awk, foi projetado para trabalhar a saída de comandos (que apenas avança, nunca retorna) linha por linha. Pra fazer subsituições voltando uma linha, vai ser necessário sed -z mesmo.

1 curtida