0

I have several files that all contain a string. This string needs to be replaced by the whole content of another file (that can possibly be multi-line). How can I do this?

What I need is something like sed -i 's/string/filename/' * where filename is an actual file and not the string "filename".

Additional info: The file can contain special characters such as / or \ or | or [ or ].

Thomas Dickey
  • 75,040
  • 9
  • 171
  • 268
Foo Bar
  • 3,462
  • 7
  • 21
  • 28

3 Answers3

2

bash works well for this:

$ cat replace
foo/bar\baz
the second line

$ cat file
the replacement string goes >>here<<

$ repl=$(<replace)

$ str="here"

$ while IFS= read -r line; do
    echo "${line//$str/$repl}"
done < file
the replacement string goes >>foo/bar\baz
the second line<<

Awk would work, except that it will interpret backslash escapes (the \b in my example)

$ awk -v string="here" -v replacement="$(<replace)" '
    {gsub(string, replacement); print}
' file
the replacement string goes >>foo/baaz
the second line<<
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
2

You need the underused sed command r which reads a file:

sed -i '/string/{r filename
                 d}'

I assume you want to replace the whole line, else replace d by something suitable.

meuh
  • 49,672
  • 2
  • 52
  • 114
  • 1
    _else_ there is nothing suitable as `r` _always inserts a newline before the ouput of a read_ – don_crissti Jun 26 '15 at 16:25
  • correct: `r` ignores the pattern space, but you can remove the `d` and do (eg) `s/string/something else/`. This changed line will appear before the file contents. – meuh Jun 26 '15 at 16:34
  • 1
    The point was that you _cannot_ insert the content of another file _inline_ if you use `r` , no matter what you do. – don_crissti Jun 26 '15 at 16:37
  • gotcha. Might be adequate for the OP though. – meuh Jun 26 '15 at 17:02
  • The bash version from the accepted answer works best for me. Nevertheless, a +1 for you because I did not know about `sed`'s `r`. – Foo Bar Jun 27 '15 at 08:36
0

I got this to work:

$ foo='baz'
$ echo "foobarbaz" | sed "s/foo/${foo}/"
bazbarbaz

Taking that one step further, your first line would be something like:

$ foo=`cat filename`

This assumes you know the filename before you reach the line to be replaced, of course - if you don't, you have to read the line, get the filename, then do the read-and-replace.

John
  • 16,759
  • 1
  • 34
  • 43