Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Possible Duplicate:
Insert a multiline string into another string

I have a file called foo.txt containing:

foo
bar
baz

I want to replace every occurence of bar with a multiline string, stored in the variable $bar:

1
2
3

Resulting in:

foo
1
2
3
baz

I can do this in awk using:

echo "$bar" | awk '{
        if(FILENAME == "-")
        {
            if(i != "")
            {
                i = i"\n"
            }
            i = i$0
        }
        else
        {
            if($0 == "bar")
            {
                printf i
            }
            else
            {
                print
            }
        }
    }'

However trying to do the same in sed using sed 's/bar/'"$bar"'/' foobar.txt gives the error:

sed: 1: "s/bar/1
2
3/": unescaped newline inside substitute pattern

Can this be fixed?

If there is an even easier way of doing this using another standard tool, I would like to know that too.

share|improve this question
add comment

marked as duplicate by Michael Mrozek Jan 4 '13 at 21:01

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2 Answers

In sed, a newline character has to be escaped in the right hand side of the s command, so you need to write it:

sed 's/foo/1\
2\
3/g'

Some sed implementations also support the (non-standard):

sed 's/foo/1\n2\n3/g'

If $bar is to be the replacement, you'd need first to insert a backslash before every newline character. While you're at it, you should also insert a backslash before every slash, backslash and ampersand character.

Something like:

bar_escaped=$(printf '%s\n' "$bar" | sed 's,[\/&],\\&,g;s/$/\\/')
bar_escaped=${bar_escaped%?}
sed "s/foo/$bar_escaped/g"
share|improve this answer
add comment

What I have done is create a sed pattern file and then call sed with that file specified instead of specifying the pattern within the command because you cannot do multi-lines on the command line (i.e. \n is not legal). E.g.

sed -f pattern_file.sed infile.txt

In my case, I wanted to find every line that reads alarm_if_fail: 1 and add application: XYZ on the very next line. So pattern_file.sed looks as follows:

1,/^END/{


        s/^alarm_if_fail: 1$/&\
application: XYZ/


}

If infile.txt looks like

Unix
Stackexchange

alarm_if_fail: 1

ABC

Then ed -f pattern_file.sed infile.txt will return

Unix
Stackexchange

alarm_if_fail: 1
application: XYZ

ABC
share|improve this answer
    
The replacement parameter is not a constant string and will change, so I can't hard code it in the pattern_file.sed. –  Tyilo Jan 4 '13 at 20:13
    
Is there any pattern to it? Regex is pretty powerful these days –  amphibient Jan 4 '13 at 20:13
    
I'm talking about the new text inserted, the replacement string. –  Tyilo Jan 4 '13 at 20:15
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.