How can I can insert the contents of a file into another file right before a specific line using sed?
example I have file1.xml that has the following:
If you can bear to make two passes, you can use a marker:
sed '/Standard/i MARKER' file1.xml | sed -e '/MARKER/r file2.xml' -e '/MARKER/d'
The trouble with trying to do it in one pass is that there's no way (that I know of) other than 'r' to insert the contents of a file, and 'r' does so in the output stream, out of reach of manipulation, after sed is finished with the line. So if the 'Standard' is in the last line, whatever you do with it will be over by the time file2 appears.
I tried the different solutions and the one from Beta did the work for me.
Summary :
Example :
Create 2 files :
cloud_config.yml:
coreos:
__ETCD2__
etcd2.yml :
etcd2:
name: __HOSTNAME__
listen-peer-urls: http://__IP_PUBLIC__:2380
listen-client-urls: http://__IP_PUBLIC__:2379,http://127.0.0.1:2379
Then we run that script on it :
sed '/Standard/i __ETCD2__' cloud_config.yml \
| sed -e "/__ETCD2__/r etcd2.yml" > tmpfile
sed "s|__ETCD2__||g" tmpfile > cloud_config.yml
Finally, we got that :
coreos:
etcd2:
name: __HOSTNAME__
listen-peer-urls: http://__IP_PUBLIC__:2380
listen-client-urls: http://__IP_PUBLIC__:2379,http://127.0.0.1:2379
f2="$(<file2)"
awk -vf2="$f2" '/StandardMessageTrailer/{print f2;print;next}1' file1
if you want sed, here's one way
sed -e '/StandardMessageTrailer/r file2' -e 'x;$G' file1
Here were the solutions that worked for me:
Using a marker like explained in another reply:
sed '/StandardMessageTrailer/i MARKER' file1.xml | sed -e '/MARKER/r file2.xml' -e '/MARKER/d'
Counting the line when it occured like explained in another reply to a similar question:
LINE_NUMBER_MATCHING=$(sed -n '/StandardMessageTrailer/=' file1.xml) && sed "$((${LINE_NUMBER_MATCHING} - 1))r file2.xml" file1.xml
Or using sed like explained in another reply to a similar question:
sed $'/StandardMessageTrailer/{e cat file2.xml\n}' file1.xml
Usually I do like this:
script snippet:
sed "\$r ${file2}" ${file1} > tmpfile
mv tmpfile ${file2}