bashsearchawkreplace

awk search and replace by a string containing "\n" will add a new line instead of writing "\n"


I use Awk to search a keyword <replaceme> and replace it by a string. This string contains the chars "\n", but Awk interprets it as a new line. I really want to keep both characters, \ and n.

I've a string containing a real new line and I need to replace it by the chars "\n". It works:

mytext=$'hello\nhow are you'
mytext2=${mytext//$'\n'/\\n}

echo "$mytext"
hello
how are you

echo "$mytext2"
hello\nhow are you

Then I have a keyword <replaceme> in a text and I would like to replace it by the content of $mytext2

echo 'this is the text: <replaceme>' |
awk -v srch="<replaceme>" -v repl="$mytext2" '{
    gsub(srch,repl,$0); print $0 }'

I get this result.

this is the text: hello
how are you

But I would like:

this is the text: hello\nhow are you

How to proceed, please?

Note: in fact, the text "this is the text: " is in a file and I use cat myfile.txt | awk...


Solution

  • You may use this awk solution:

    mytext=$'hello\nhow are you'
    echo 'this is the text: <replaceme>' |
    awk -v srch="<replaceme>" -v repl="${mytext//$'\n'/\\\\n}" '{gsub(srch,repl)} 1'
    
    this is the text: hello\nhow are you
    

    BASH replacement ${mytext//$'\n'/\\\\n} will replace each instance of \n with \\n before passing that string as awk argument repl.


    Pure awk solution (without bash):

    echo 'this is the text: <replaceme>' |
    awk -v srch="<replaceme>" '
    BEGIN {
       repl = ARGV[1]
       gsub(/\n/, "\\n", repl)
       delete ARGV[1]
    }
    {
       gsub(srch, repl)
    } 1' "$mytext"
    
    this is the text: hello\nhow are you