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 ].

1

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<<
  • For my intented use case the bash version works best and is the most flexible. Thanks. :) – Foo Bar Jun 27 '15 at 8:34
1

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.

  • 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 8: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.

  • Will this work without checking for escape characters or escaping control characters? Example: the file contains the character /. – Foo Bar Jun 26 '15 at 13:51
  • I honestly don't know, but given how often I run in to that problem, I'm going to bet it won't. – John Jun 26 '15 at 13:53
  • Actually, it might: foo="baz\bak" followed by the echo | sed works. – John Jun 26 '15 at 13:55
  • sed will complain if $foo contains the delimiter for the s/// command – glenn jackman Jun 26 '15 at 14:41
  • 1
    ...not to mention that if the replacement file has more than one line then s/../../ won't work anyway... – don_crissti Jun 26 '15 at 16:24

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.