Linux – SED replace across multiple lines

bashlinuxsed

I am trying to find these three lines:

<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->

and replace them with:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

When I try

sudo sed -i 's:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

It doesn't find it, I also tried to put \n in it, but it still didn't work:

sudo sed -i 's:<!--\n <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />\n -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

These don't throw any errors it just doesn't uncomment the line. Any advice would help thanks!

Best Answer

sed reads each line in turn, so it'll never match a multiline pattern unless you nudge it in the right direction. The N command reads one line from the input and appends it to the pattern space.

sed -i -e '/^<!--$/ {
    N; /\n<Connector port="8009" protocol="AJP\/1\.3" redirectPort="8443" \/>$/ {
        N; /\n-->$/ {
            s/^<!--\n//; s/\n-->$//
        }
    }
}' /myfile.xml

Arguably, if you need a command other than s, then you should switch away from sed and to awk or perl. Here's a slightly more flexible Perl snippet that copes with multiline comments in a more general way.

perl -i -pe '
    if (/<!--/) { $_ .= <> while !/-->/;
        s[<!--\n(<Connector port="8009" protocol="AJP/1\.3" redirectPort="8443" />)\n-->][$1];
    }' /myfile.xml
Related Topic