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?

Braiam
  • 35,991
Sam
  • 255

4 Answers4

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.

Ramesh
  • 39,297
  • This worked great. Thank you. What is the purpose of the delete command? – Sam Aug 26 '14 at 03: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 '14 at 03:49
  • @Ramesh: Without d, PATTERN remain in the file. – cuonglm Aug 26 '14 at 05: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. – Stéphane Chazelas Aug 26 '14 at 05: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

Ramesh
  • 39,297
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
  • 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 '19 at 06: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
mikeserv
  • 58,310