sed - String durch Dateiinhalt ersetzen

21

Ich habe zwei Dateien: file1und file2.

file1 hat folgenden Inhalt:

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

file2enthält eine IP-Adresse ( 1.1.1.1)

Was ich will , ist zu tun , ersetzen localhostmit 1.1.1.1, so dass das Endergebnis ist:

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

Ich habe versucht:

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

Aber ich bekomme entweder die ganze Leitung ersetzt, oder die IP geht auf die Leitung nach der, die ich ändern muss.

Jay Kah
quelle
1
nicht sicher, aber funktioniert das cat file1 | sed -e 's/localhost/1.1.1.1/g'?
Dchirikov
1
Schau dir den \rsed Befehl an.
Kevin

Antworten:

14

Hier ist eine sedLösung:

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

Sie sollten verwenden sed -i, um die Änderung zu übernehmen.

Wenn Sie verwenden können awk, haben Sie folgende Möglichkeiten:

% 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
quelle
4
+1 für awk. Ich stelle mir sed ist dazu in der Lage, aber es wird furchtbar ungeschickt sein. Hier awkscheint!
HalosGhost
1
@ HalosGhost: Es sieht so aus, als ob ich und Sie die OP-Frage falsch verstanden haben. Ich habe meine Antwort aktualisiert.
Cuonglm
Die Befehlsersetzung für die sedLösung sollte in doppelte Anführungszeichen gesetzt werden, wenn die Datei Leerzeichen oder Glob-Zeichen enthält.
Graeme
@Graeme: Danke, aktualisiert! Fühlen Sie sich frei, eine Bearbeitung vorzunehmen.
Cuonglm
2
Sie müssen beide entkommen /und &in der Substitution. Das ist"$(sed 's:[/\\&]:\\&:g' file2)"
Toby Speight
6

Sie können die Datei mit der Ersetzungszeichenfolge mithilfe der Shell-Befehlsersetzung lesen, bevor sie sedverwendet wird. Also sedwird es nur eine normale Substitution geben:

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

Volker Siegel
quelle
18
Funktioniert dies bei mehrzeiligen Dateien und Dateien mit Sonderzeichen?
Trevor Hickey,
9
@ TrevorHickey tut es nicht. Sed schlägt nur mit einem "nicht abgeschlossenen" Befehl fehl.
DarioP
1

Versuchen Sie es mit

join file1 file2

Entfernen Sie dann alle unerwünschten Felder.

entmutigen
quelle
1

Ich hatte heute auch dieses "Problem": wie man einen Textblock durch den Inhalt einer anderen Datei ersetzt.

Ich habe es gelöst, indem ich eine Bash-Funktion erstellt habe (die in Skripten wiederverwendet werden kann).

[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
quelle