1

I'm lost trying to do following substitution with sed:

@ edit: to capture the full complexity of my problem, I added the fact that filenames are contained in variables afterwards. Solutions might therefore directly use the filenames.

given a variable I='insert.txt':

'insert.txt':

Text I wanna skip.

This is text to insert containing
spaces and new lines

given a variable M='toModify.txt':

'toModify.txt':

Insert the new text: here.

I would like to replace the 'here' from $M with the content of $I:

Insert the new text: This is text to insert containing
spaces and new lines.

I tried:

sed -e "s/here/$(tail -n2 $I | sed -e 's/ /\\ /g' | tr '\n' '\\n')/" $M

with error: sed unterminated `s' command

The problem is that I don't get the spaces and new lines without terminating the s command.

Any solution?

Josja
  • 131
  • 7
  • 1
    Please add your desired output for that sample input to your question. – Cyrus Nov 01 '18 at 19:57
  • Very similar to [Use the contents of a file to replace a string using SED](https://stackoverflow.com/questions/6790631/use-the-contents-of-a-file-to-replace-a-string-using-sed). There is a fine difference, but that answer may help you. – Socowi Nov 01 '18 at 20:43
  • In `insert.txt`, how do you differentiate between text to be skipped and text to be inserted? – Socowi Nov 01 '18 at 20:59

3 Answers3

0

You may use this awk:

awk 'BEGIN{prs=RS; RS=""; getline s < "insert.txt"; RS=prs}
{gsub(/here/, s)} 1' toModify.txt

Insert the new text: This is text to insert containing
spaces and new lines.
anubhava
  • 761,203
  • 64
  • 569
  • 643
0

You can't replace one character with two with tr. Escaping the individual spaces is pointless anyway. The reason for the immediate error is that you end up escaping the final slash, too:

linux$ tail -n2 "$I" | sed -e 's/ /\\ /g' | tr '\n' '\\n'
This\ is\ text\ to\ insert\ containing\spaces\ and\ new\ lines\/

Escaping the spaces is pointless anyway. I guess you want something like this:

linux$ sed '1,2d;$!s/$/\\/' "$I"
This is text to insert containing\
spaces and new lines

We delete lines 1 and two; then add a backslash before every newline except the last.

linux$ sed -e "s/here/$(sed '1,2d;$!s/$/\\/' "$I")/" "$M"
Insert the new text: This is text to insert containing
spaces and new lines.

This is one detail of sed which isn't entirely portable. But the above works for me on Linux and MacOS. (Note you might need to set +H to disable csh-style history expansion aka -bash: !s/$/\\/': event not found errors).

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thank you, that solved my problem! Could you explain what the \ is actually doing? Is it interpreted as a continuation character before the new line? – Josja Nov 02 '18 at 10:02
  • Yeah, it escapes the newline so `sed` knows the text continues on the next line. – tripleee Nov 02 '18 at 10:03
0

Using Perl one-liner

> cat insert.txt
This is text to insert containing
spaces and new lines
> cat toModify.txt
Insert the new text: here
> export I=insert.txt
> export M=toModify.txt
> perl -ne 'BEGIN{$x=qx(cat $ENV{M});$x=~s/here/qx(cat $ENV{I})/e; print $x;exit }'
Insert the new text: This is text to insert containing
spaces and new lines

>
stack0114106
  • 8,534
  • 3
  • 13
  • 38