sed replace with variable with multiple lines

10,722

Solution 1

An interesting question..

This may get you closer to a solution for your use case.

read -r -d '' TEST <<EOI
a\\
b\\
c
EOI

echo TOREPLACE | sed -e "s/TOREPLACE/${TEST}/"
a
b
c

I hope this helps.

Solution 2

Given that you're using Bash, you can use it to substitute \n for the newlines:

sed -e "s/TOREPLACE/${TEST//$'\n'/\\n}/" file.txt

To be properly robust, you'll want to escape /, & and \, too:

TEST="${TEST//\\/\\\\}"
TEST="${TEST//\//\\/}"
TEST="${TEST//&/\\&}"
TEST="${TEST//$'\n'/\\n}"
sed -e "s/TOREPLACE/$TEST/" file.txt

If your match is for a whole line and you're using GNU sed, then it might be easier to use its r command instead:

sed -e $'/TOREPLACE/{;z;r/dev/stdin\n}' file.txt <<<"$TEST"

Solution 3

You can just write the script as follows:

sed -e 's/TOREPLACE/a\
b\
c\
/g' file.txt

A little cryptic, but it works. Note also that the file won't be modified in place unless you use the -i option.

Solution 4

tricky... but my solution would be :-

read -r -d '' TEST <<EOI
a
b
c
EOI

sed -e "s/TOREPLACE/`echo "$TEST"|awk '{printf("%s\\\\n", $0);}'|sed -e 's/\\\n$//'`/g" file.txt

Important: Make sure you use the correct backticks, single quotes, double quotes and spaces else it will not work.

Share:
10,722
Andreas
Author by

Andreas

Updated on July 31, 2022

Comments

  • Andreas
    Andreas over 1 year

    I am trying to replace a word with a text which spans multiple lines. I know that I can simply use the newline character \n to solve this problem, but I want to keep the string "clean" of any unwanted formatting.

    The below example obviously does not work:

    read -r -d '' TEST <<EOI
    a
    b
    c
    EOI
    
    sed -e "s/TOREPLACE/${TEST}/" file.txt
    

    Any ideas of how to achieve this WITHOUT modifying the part which starts with read and ends with EOI?

  • Andreas
    Andreas almost 13 years
    Thanks. I know about the -i option. Actually, I want to use a variable for better readability and I do not want to touch the contents of the variable. Actually ... it's rather that I would like to know how I can do this for future reference. Do you know a solution to this problem that does not involve the modification of the first 5 lines?
  • Diego Sevilla
    Diego Sevilla almost 13 years
    The question is that the read converts the carriage returns into spaces, so you should be inserting the carriage returns again anyway.
  • Andreas
    Andreas over 12 years
    For the moment I will go with this ... interestingly, that doesn't seem to be as trivial as I thought it was ... thanks