Search code examples
bashsedsubstitutionend-of-line

Bash. Replace with sed. End of line problem


I am trying to search and replace in file using sed. But sed seems to hate end of line special char.

text=$(shuf text.txt)
echo "This is text:
$text"
sed -i "s~%text%~$text~g" t.txt

Here is what I get:

This is text:
 line 2
 line 1
 line 3
 line 4
sed: -e expression #1, char 15: unterminated `s' command

I've tried to replace \n with \r but result is not satisfying at all. There is an option to do tr '\n' , '$' and then do it backwards afterwards but it doesn't seems right.

Help?


Solution

  • Using sed and bash

    Since you are using bash, try:

    sed -i "s~%text%~${text//$'\n'/\\n}~g" t.txt
    

    ${text//$'\n'/\\n} is an example of bash's pattern substitution. In this case, it replaces all newline characters with with backslash followed by n which sed will interpret as a newline.

    Example

    Consider this text variable:

    $ echo "$text"
    line 2
     line 1
     line 3
     line 4
    

    And this input file:

    $ cat t.txt
    start
    %text%
    end
    

    Now, run our command:

    $ sed "s~%text%~${text//$'\n'/\\n}~g" t.txt
    start
    line 2
     line 1
     line 3
     line 4
    end
    

    To change the file in-place, of course, add the -i option back.

    Using awk

    With the same text variable and t.txt file as above:

    $ awk -v new="$text" '{gsub(/%text%/, new)} 1' t.txt
    start
    line 2
     line 1
     line 3
     line 4
    end