sed - sostituisce la stringa con il contenuto del file


22

Ho due file: file1e file2.

file1 ha i seguenti contenuti:

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

file2contiene un indirizzo IP ( 1.1.1.1)

Quello che voglio fare è sostituirlo localhostcon 1.1.1.1, in modo che il risultato finale sia:

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

Ho provato:

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

Ma ottengo la sostituzione dell'intera linea o l'IP passa alla riga dopo quella che devo modificare.


1
non sono sicuro, ma cat file1 | sed -e 's/localhost/1.1.1.1/g'funziona?
dchirikov,

1
Guarda il \rcomando sed.
Kevin,

Risposte:


14

Ecco una sedsoluzione:

% 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"

È necessario utilizzare sed -iper apportare la modifica sul posto.

Se puoi usare awk, ecco un modo per fare:

% 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"

4
+1 per awk. Immagino sed sia capace di questo, ma sarà terribilmente maldestro. Questo è dove awkbrilla!
HalosGhost

1
@HalosGhost: sembra sia a me che tu abbia frainteso la domanda OP, ho aggiornato la mia risposta.
cuonglm,

La sostituzione del comando per la sedsoluzione deve essere racchiusa tra virgolette nel caso in cui il file contenga spazi o caratteri glob.
Graeme,

@Graeme: grazie, aggiornato! Sentiti libero di fare un montaggio.
cuonglm,

2
Hai bisogno di fuggire sia /e &nella sostituzione. Cioè"$(sed 's:[/\\&]:\\&:g' file2)"
Toby Speight,

6

È possibile leggere il file con la stringa di sostituzione utilizzando la sostituzione del comando shell, prima che sedvenga utilizzato. Quindi sedvedrà solo una normale sostituzione:

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


18
Funziona su file a più righe e file con caratteri speciali?
Trevor Hickey,

9
@TrevorHickey non è così. Sed fallisce semplicemente con un errore "comando 's non terminato".
DarioP

1

Prova a usare

join file1 file2

e quindi rimuovere tutti i campi indesiderati.


1

Ho avuto anche questo "problema" oggi: come sostituire un blocco di testo con i contenuti di un altro file.

L'ho risolto creando una funzione bash (che può essere riutilizzata negli script).

[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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.