Substitua string pelo conteúdo de um arquivo usando sed


23

Eu tenho dois arquivos diferentes:

Arquivo1

/home/user1/  
/home/user2/bin  
/home/user1/a/b/c

Arquivo2

<TEXT1>
<TEXT2>

Eu quero substituir o <TEXT1>do File2 com o conteúdo do File1 usando sed. Eu tentei este comando, mas não obtendo saída adequada:

cat File2|sed "s/<TEXT1>/$(cat File1|sed 's/\//\\\//g'|sed 's/$/\\n/g'|tr -d "\n")/g"

Você também pode usar outras ferramentas para resolver esse problema.


Cole essa mensagem de erro para que possamos localizar sua fonte. Diga-nos também qual sedimplementação você está usando. Seu código funciona para mim com o GNU sed.
— manatwork

Desculpe, não está recebendo um erro. Não estou obtendo a saída desejada. Saída é como /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. Não recebendo novas linhas.
— chanchal1987

Não tenho certeza se isso se aplicaria no seu caso específico, mas as ferramentas com diffe patchpermitem substituir algumas linhas em um arquivo por outras com bastante facilidade.
— Stéphane Gimenez

1
Aliás, usar dados aleatórios reunidos $()em um script sed faz meus olhos sangrarem. Nunca use dados externos em locais onde alguns caracteres são interpretados com significado especial.
— Stéphane Gimenez

Respostas:


24

Aqui está uma solução de script sed (mais fácil para os olhos do que tentar colocá-la em uma linha na linha de comando):

/<TEXT1>/ {
  r File1
  d
}

Executando:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>

Obrigado, isso está funcionando. Mas não quero usar nenhum outro arquivo de script. Existe alguma solução em linha?
— chanchal1987

Claro:, sed '/<TEXT1>/{rFile1^Md^M}' File2onde "^ M" é você pressionando return. O problema é que o sed realmente precisa das novas linhas dentro do {...} para delimitar os comandos re d.
— Kusalananda

6
com bash, cordas de estilo POSIX são um pouco mais limpo:sed $'/<TEXT1>/ {r File1\n d}'
— Glenn Jackman

9
Também com -e para um liner:sed -e '/<TEXT1>/{r File1' -e 'd}' File2
— sdaau

1
E se, em vez de substituir toda a linha que contém <TEXT1>, eu apenas quero substituir a própria string, deixando o resto da linha intacta? Text1: <TEXT1>para Text1: <file_contents>.
— Robin Winslow

9

Levei muito tempo para encontrar esta solução usando a substituição de var. Todas as soluções sed não funcionaram para mim, pois excluem linhas completas ou substituem incorretamente.

FILE2=$(<file2)
FILE1=$(<file1)
echo "${FILE2//TEXT1/$FILE1}" 

Substitui todas as ocorrências de TEXT1 no arquivo2 pelo conteúdo do arquivo1. Todo o outro texto permanece intocado.


muito agradável. possivelmente mais rápido do que sedtambém, uma vez que essas "expansões" (também conhecidas como substituições) são incorporadas ao shell ( bashpelo menos)
— amarelo-amarelado

7

Eu respondo porque o método diff/ patchpode ser interessante em alguns casos. Para definir uma substituição de linhas contidas no arquivo blob1por linhas contidas em blob2uso:

diff -u blob1 blob2 > patch-file

Por exemplo, se blob1contém:

hello
you

e blob2contém:

be
welcome
here

o gerado patch-fileserá:

--- blob1   2011-09-08 16:42:24.000000000 +0200
+++ blob2   2011-09-08 16:50:48.000000000 +0200
@@ -1,2 +1,3 @@
-hello
-you
+be
+welcome
+here

Agora, você pode aplicar esse patch a qualquer outro arquivo:

patch somefile patch-file

Ele irá substituir hello, youlinhas por be, welcome, herelinhas em somefile.


isso é realmente inteligente, mas seria melhor se você pudesse automatizá-lo em um script
— qodeninja
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.