21

I have two files: file1 and file2.

file1 has the following contents:

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

file2 contains an IP address (1.1.1.1)

What I want to do is replace localhost with 1.1.1.1, so that the end result is:

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

I have tried:

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

But I either get the whole line replaced, or the IP going to the line after the one I need to modify.

  • 1
    not sure, but does cat file1 | sed -e 's/localhost/1.1.1.1/g' work? – dchirikov Jul 8 '14 at 18:57
  • 1
    Look at the \r sed command. – Kevin Jul 19 '14 at 15:01
14

Here is a sed solution:

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

You should use sed -i to make the change inplace.

If you can use awk, here is one way to do:

% 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 for awk. I imagine sed is capable of this, but it will be terribly clumsy. This is where awk shines! – HalosGhost Jul 8 '14 at 19:14
  • 1
    @HalosGhost: It's seem both me and you had misunderstand the OP question, I updated my answer. – cuonglm Jul 8 '14 at 19:25
  • The command substitution for the sed solution should be double quoted in case the file contains spaces or glob characters. – Graeme Jul 8 '14 at 19:38
  • @Graeme: Thanks, updated! Feel free to make an editting. – cuonglm Jul 8 '14 at 19:39
  • 2
    You need to escape both / and & in the substitution. That's "$(sed 's:[/\\&]:\\&:g' file2)" – Toby Speight Dec 6 '16 at 12:40
5

You can read the file with the replacement string using shell command substitution, before sed is used. So sed will see just a normal substitution:

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

  • 18
    Does this work on multi-lined files and files with special characters? – Trevor Hickey Jun 12 '15 at 18:23
  • 9
    @TrevorHickey it doesn't. Sed just fails with an "unterminated `s' command" error. – DarioP Oct 7 '16 at 11:16
1

Try using

join file1 file2

and then, remove any unwanted fields.

0

I also had this "problem" today: how to replace a block of text with the contents from another file.

I've solved it by making a bash function (that can be reused in 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.