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.