Kyle.Tryon
Kyle.Tryon

Reputation: 54

Bash replace line in a file with multiline file

I have a text file which has some place holder values:

Example:

Parent:
   Child: x
   Child2: <place-holder>

Car:
   Seat: x
   Door: <place-holder>

I am accomplishing this with sed in a way that works on both MacOS and Linux

sed -i .bak "s/<place-holder>/$REPLACEMNET_VALUE/g" file.yml

What I need to accomplish now is one step further, to inject a section in this file.

I have a file with several lines in the proper format and the location of that file in an environment variable.

sed -i .bak "s/<place-holder-section>/$(<$CONFIG_OPTIONS_TEMP)/g" config.yml

However, sed seems to not be able to handle multiple lines (without escaping).

Error:

sed: 1: "s/<place-holder-section>/ f ...": unescaped newline inside substitute pattern

This could probably be solved with some looping and grepping for the line position and such but I am hoping maybe someone has a more elegant solution, possibly using awk? Keeping MacOS cross-compatibility is a concern as well.

Upvotes: 1

Views: 283

Answers (2)

potong
potong

Reputation: 58578

This might work for you (GNU sed):

sed -e '/<foo>/{r insertFile' -e 'd}' file

On encountering a line containing <foo> replace it by the contents of insertFile.

N.B. The solution consists of two parts: the r insertFile needs to normally end in a newline but the -e option can emulate this, thus the second part is likewise introduced with another -e option that deletes the found line. The d must also be the last command as any other commands following it, will never by executed.

Upvotes: 0

Brenda J. Butler
Brenda J. Butler

Reputation: 1485

Sed has another command 'r filename' "append text read from filename". So if all the text to be inserted is in a file by itself, you could use this sed command.

Example:

bjb@blueeyes:~$ cat /tmp/old
Parent:
  Child: x
  Child2: <place-holder>

Car:
  Seat: x
  Door: <place-holder2>


<foo>


bjb@blueeyes:~$ cat /tmp/new
CarSeat:
    padding: fluff
    belt:  seat-belt-stuff

bjb@blueeyes:~$ sed '/<foo>/ {
> x
> r /tmp/new
> }' /tmp/old
Parent:
  Child: x
  Child2: <place-holder>

Car:
  Seat: x
  Door: <place-holder2>



CarSeat:
    padding: fluff
    belt:  seat-belt-stuff



bjb@blueeyes:~$ 

The sed command is addressed to the marker in file /tmp/old - it puts that line in the hold space and never retrieves it so it has the effect of replacing the marker with the contents of the file /tmp/new.

Upvotes: 2

Related Questions