Boon
Boon

Reputation: 1173

Using sed with a newline in a regex

I'm bashing my head against the wall with this one. How do I do a regex replacement with sed on text that contains a newline?

I need to replace the value of the "version" XML element shown below. There are multiple version elements so I want to replace the one that comes after the "name" element.

<name>MyName</name>
<version>old</version>

Here's my command:

sed -i -E "s@(\s*<name>$NAME</name>\n\s*<version>)$VERSION_OLD(</version>)@\1$VERSION_NEW\2@g" $myfile.txt

Now as far as I know there is a way to make sed work with a newline character, but I can't figure it out. I've already used sed in my script so ideally I'd prefer to re-use it instead of say perl.

Upvotes: 0

Views: 1376

Answers (2)

Toby Speight
Toby Speight

Reputation: 30968

If you're using GNU sed, you can use its extended addressing syntax:

sed '/<name>/,+1{/<version>/s/old/newer/}' file

Breaking this down, it says: for a line matching <name> and the following line (+1), then if the line matches <version>, substitute old with newer.

I'm assuming here that your file is generated, and will always have the name and version elements each on a single line, and adjacent. If you need to handle more free-form XML, then you should really consider an XPath-based tool rather than sed.

Upvotes: 0

Cyrus
Cyrus

Reputation: 88929

When you see your name element, you will need to use the N command to read the next line:

file:

<bar>MyName</bar>
<version>old</version>
<name>MyName</name>
<version>old</version>
<foo>MyName</foo>
<version>old</version>

With GNU sed:

sed '/<name>/{N;s/old/newer/}' file

Output:

<bar>MyName</bar>
<version>old</version>
<name>MyName</name>
<version>new</version>
<foo>MyName</foo>
<version>old</version>

Upvotes: 3

Related Questions