11

I'm attempting to replace a pattern in a file with the complete contents of another file using sed.

Currently I am using:

sed "s/PATTERN/`cat replacement.txt`/g" "openfile.txt" > "output.txt"

However, if the replacement file contains any characters such as ', ", or / I start getting errors due to input not being sanitized.

I have been trying to use this guide to aid me, but I am finding it quite hard to follow. If I try the suggested r file command, I just end up with a string.

What is the best way to approach this?

0

4 Answers 4

7

This should work for you. I did not vote to close as duplicate since you had specified you have ', / and " characters in your file. So, I did the testing as below.

I have file1 contents as below.

cat file1
ramesh' has " and /
in this file
and trying
"to replace'
the contents in 
/other file.

Now, file2 is as below.

cat file2
This is file2
PATTERN 
After pattern contents go here. 

As per the shared link, I created the script.sed as below.

cat script.sed
/PATTERN/ {
  r file1
  d
}

Now, when I run the command as sed -f script.sed file2, I get the output as,

This is file2
ramesh' has " and /
in this file
and trying
"to replace'
the contents in 
/other file.
After pattern contents go here. 

EDIT: This works well with multiple patterns in the file as well.

4
  • This worked great. Thank you. What is the purpose of the delete command?
    – Sam
    Aug 26, 2014 at 3:45
  • @Sam, do you mean the d at the end of script.sed file? I tried removing it and ran it and still got the same output. So, I am not sure what exactly it does.
    – Ramesh
    Aug 26, 2014 at 3:49
  • @Ramesh: Without d, PATTERN remain in the file.
    – cuonglm
    Aug 26, 2014 at 5:15
  • 3
    Note that it doesn't replace PATTERN with the content of the file, but any full line containing PATTERN with the content of the file. Aug 26, 2014 at 5:52
4

If you need an awk solution, you could use something like below.

 awk '/PATTERN/{system("cat file1");next}1' file2

Testing

cat file1
ramesh' has " and /
in this file
and trying
"to replace'
the contents in 
/other file.

Now, I have file2 as below.

cat file2
This is file2
PATTERN 
After pattern contents go here.
PATTERN 

Now, I use the above mentioned awk command.

Output:

This is file2
ramesh' has " and /
in this file
and trying
"to replace'
the contents in 
/other file.
After pattern contents go here.
ramesh' has " and /
in this file
and trying
"to replace'
the contents in 
/other file.

References

http://www.unix.com/shell-programming-and-scripting/158315-replace-string-contents-txt-file-containing-multiple-lines-strings.html

4
  • I appreciate that you took the time to provide two solutions. Thank you.
    – Sam
    Aug 26, 2014 at 3:45
  • @Ramesh: This awk won't work if line have something like QWERTY PATTERN. It skip the whole line instead of replace PATTERN.
    – cuonglm
    Aug 26, 2014 at 5:13
  • @cuonglm is there a way to make this filename(file1 - which is providing stdout using cat) variable in this command?
    – fireball.1
    May 19, 2020 at 20:18
  • @fireball.1 You can use ARGV variable to access arguments.
    – cuonglm
    May 20, 2020 at 7:10
2

In:

sed "s/PATTERN/`cat replacement.txt`/g" "openfile.txt"

' and " should not be a problem. Those are not special to sed. What should be a problem is &, \, / and newline. You can escape those with another sed command:

sed "s/PATTERN/$(sed 's@[/\&]@\\&@g;$!s/$/\\/' replacement.txt)/g" openfile.txt

Note that it removes the trailing newline characters in replacement.txt. If that's not want you want, you can do

replacement=$(sed 's@[/\&]@\\&@g;s/$/\\/' replacement.txt; echo .)
replacement=${replacement%.}
sed "s/PATTERN/$replacement/g" openfile.txt
1
  • Thanks, but how does it work running "sed 's@[/\&]@\\&@g;$!s/$/\\/' replacement.txt" escapes the problem chars, but how are they removed when inserted to openfile.txt ?
    – Sumit Jain
    May 22, 2019 at 6:42
1

With GNU sed you can just execute cat at whatever point of the script you like. Unlike r - which schedules for output for the end of the line cycle (which can be very frustrating!), e works like i or c in that it immediately writes its output. Here are some examples of its use:

printf %s\\n 'these are some words' \
    'that will each appear' \
    'on their own line' | 
    sed 's/.*words/echo & ; cat file/e'
these are some words
these
are
some
more
words    
that
are
stored
in
a
file
that will each appear
on their own line

And here's how you might use this:

printf %s\\n 'these are some words' \
    'that will each appear' \
    'on their own line' | 
sed 's/\(.*\)\n*words/\1\n&/;//P;s//\ncat file/ep;s/.*\n//'
these are some 
these
are
some
more
words
that
are
stored
in
a
file
that will each appear
on their own line

Not the answer you're looking for? Browse other questions tagged .