sed - substitui a string pelo conteúdo do arquivo

21

Eu tenho dois arquivos: file1e file2.

file1 tem o seguinte conteúdo:

---
  host: "localhost"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "localhost:2181"

file2contém um endereço IP ( 1.1.1.1)

O que eu quero fazer é substituir localhostcom 1.1.1.1, de modo que o resultado final é:

---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"

Eu tentei:

sed -i -e "/localhost/r file2" -e "/localhost/d" file1
sed '/localhost/r file2' file1 |sed '/localhost/d'
sed -e '/localhost/r file2' -e "s///" file1

Mas eu substituo a linha inteira ou o IP vai para a linha após a que eu preciso modificar.

Jay Kah
fonte
1
não tenho certeza, mas cat file1 | sed -e 's/localhost/1.1.1.1/g'funciona?
dchirikov 8/07
1
Veja o \rcomando sed.
19714 Kevin

Respostas:

14

Aqui está uma sedsolução:

% sed -e "s/localhost/$(sed 's:/:\\/:g' file2)/" file1
---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"

Você deve usar sed -ipara fazer a alteração no local.

Se você pode usar awk, aqui está uma maneira de fazer:

% awk 'BEGIN{getline l < "file2"}/localhost/{gsub("localhost",l)}1' file1
---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"
cuonglm
fonte
4
+1 para awk. Imagino que sed seja capaz disso, mas será terrivelmente desajeitado. É aqui que awkbrilha!
precisa saber é o seguinte
1
@HalosGhost: Parece que eu e você não entendemos a pergunta do OP, atualizei minha resposta.
18714 cuuvlm
A substituição do comando para a sedsolução deve ser citada duas vezes, caso o arquivo contenha espaços ou caracteres glob.
Graeme
@ Graeme: Obrigado, atualizado! Sinta-se livre para fazer uma edição.
18714 cuuvlm
2
Você precisa escapar de ambos /e &na substituição. Isso é #"$(sed 's:[/\\&]:\\&:g' file2)"
Toby Speight
6

Você pode ler o arquivo com a sequência de substituição usando a substituição do comando shell, antes de sedser usado. Então sed, veremos apenas uma substituição normal:

sed "s/localhost/$(cat file2)/" file1 > changed.txt

Volker Siegel
fonte
18
Isso funciona em arquivos com várias linhas e com caracteres especiais?
Trevor Hickey
9
@TrevorHickey isso não acontece. O Sed simplesmente falha com o erro "comando não terminado" s ".
DarioP 07/10
1

Tente usar

join file1 file2

e remova todos os campos indesejados.

unxnut
fonte
1

Eu também tive esse "problema" hoje: como substituir um bloco de texto pelo conteúdo de outro arquivo.

Eu o resolvi criando uma função bash (que pode ser reutilizada em scripts).

[cent@pcmk-1 tmp]$ cat the_function.sh
# This function reads text from stdin, and substitutes a *BLOCK* with the contents from a FILE, and outputs to stdout
# The BLOCK is indicated with BLOCK_StartRegexp and BLOCK_EndRegexp
#
# Usage:
#    seq 100 110 | substitute_BLOCK_with_FILEcontents '^102' '^104' /tmp/FileWithContents > /tmp/result.txt
function substitute_BLOCK_with_FILEcontents {
  local BLOCK_StartRegexp="${1}"
  local BLOCK_EndRegexp="${2}"
  local FILE="${3}"
  sed -e "/${BLOCK_EndRegexp}/a ___tmpMark___" -e "/${BLOCK_StartRegexp}/,/${BLOCK_EndRegexp}/d" | sed -e "/___tmpMark___/r ${FILE}" -e '/___tmpMark___/d'
}

[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ cat /tmp/FileWithContents
We have deleted everyhing between lines 102 and 104 and
replaced with this text, which was read from a file
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ source the_function.sh
[cent@pcmk-1 tmp]$ seq 100 110 | substitute_BLOCK_with_FILEcontents '^102' '^104' /tmp/FileWithContents > /tmp/result.txt
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ cat /tmp/result.txt
100
101
We have deleted everyhing between lines 102 and 104 and
replaced with this text, which was read from a file
105
106
107
108
109
110
zipizap
fonte