Substituir padrão em um arquivo pelo conteúdo de outro arquivo

20

Eu tenho um arquivo de texto ( devel.xml).

Adicionei a palavra REPLACETHIS para substituir esta string pelo conteúdo em um arquivo diferente ( temp.txt).

A coisa mais próxima que tenho é esta:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

Isso insere o conteúdo após a sequência e exclui a sequência posteriormente.

Esse é o melhor jeito de fazer isso?

RafaelGP
fonte
Tem que ser sed? Dependendo da quantidade de texto em temp.txt, eu posso avançar para uma solução perl.
user17591

Respostas:

34

O que você fez foi remover SUBSTITUTETHISonde quer que ele apareça no arquivo (mas não o restante da linha em que aparece) e inserir o conteúdo temp.TXTabaixo dessa linha. Se SUBSTITUTETHISaparecer várias vezes em uma linha, apenas a primeira ocorrência será removida e apenas uma cópia temp.TXTserá adicionada.

Se você deseja substituir a linha inteira quando SUBSTITUTETHISaparecer, use o dcomando Como você precisa executar os dois re dquando houver uma correspondência, coloque-os em um grupo preparado.

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

Algumas implementações sed permitem usar ponto-e-vírgula para separar comandos e omitir completamente os separadores entre chaves, mas você ainda precisa de uma nova linha para finalizar o argumento do rcomando:

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

Se você deseja substituir SUBSTITUTETHISpelo conteúdo do arquivo, mas reter o que vem antes e depois na linha, é mais complicado. O método mais simples é incluir o conteúdo do arquivo no comando sed; observe que você precisará citar adequadamente seu conteúdo.

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

Ou use Perl. Isso é curto, mas é executado catuma vez para cada substituição:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

Para ler o arquivo uma vez quando o script iniciar, e evite depender de um comando do shell:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

(apresentado em duas linhas para facilitar a leitura, mas você pode omitir a quebra de linha). Se o nome do arquivo for variável, para evitar problemas de citação, passe-o para o script por meio de uma variável de ambiente:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt
Gilles 'SO- parar de ser mau'
fonte
Como eu poderia mudar o comando perl para que ao invés de cat temp.txteu pudesse fazer cat ${variable}?
Maria Ines Parnisari 30/08
@MariaInesParnisari Cometi um erro na formatação de comentários. Veja minha resposta, com uma solução um pouco diferente e mais robusta.
Gilles 'SO- stop be evil'
Como o File :: Slurp nem sempre é instalado, uma alternativa é usar a -0777opção slurp no arquivo inteiro, e uma maneira regular open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk
Como quebrar r temp.TXTcom mensagens como "BEGIN temp.TXT", "END temp.TXX"
kyb
Encontrei solução para minha pergunta. Use o acomando (adicionar). Grymoire.com/Unix/Sed.html#uh-36
kyb