1

I'm trying to do some pretty simple sedding of a file:

sed 's:(?<=<Type>)default(?=</Type>):super:' < myfile.xml

The concept's pretty simple, using positive lookaround, find the tags and replace the contents with "super". Unfortunately, it doesn't work, nothing is replaced. What am I doing wrong?

I'm looking to "edit" a file similar to this:

<Hello>
    <World>
        <Type>default</Type>
    </World>
</Hello>

so that it looks like this:

<Hello>
    <World>
        <Type>super</Type>
    </World>
</Hello>
Naftuli Kay
  • 39,676

3 Answers3

3

Your regular expression is correct, but sed does not handle lookarounds. Your code works fine with perl:

perl -pe 's:(?<=<Type>)default(?=</Type>):super:' your.file

As regular expressions are generally not really good in XML handling, I suggest to try XMLStarlet:

xml ed -O -u '//Type' -v 'super' your.file

Both perl and xml can do in-place editing too, so adds no pain replacing sed.

manatwork
  • 31,277
  • Now I understand what was strange to me in the OP sed script: it uses perl syntax in sed, and I don't know perl. Thanks to clarify. – enzotib Nov 10 '11 at 09:14
  • Thank you! You understood what I was trying to do :) That's EXACTLY what I meant! – Naftuli Kay Nov 10 '11 at 09:27
1

You're trying to use Perl regular expression syntax in sed; this won't work. Sed uses basic regular expressions; Perl uses extended regular expressions with more features. Lookaround is one of the Perl-specific features; it's found in other modern regexp implementations, but not in sed.

You don't need lookaround here. Positive lookaround at the beginning or end of a pattern you're replacing can easily be turned into a variable replacement text. See also Return only the portion of a line after a matching pattern for more examples and explanations.

sed 's:\(<Type>\)default\(</Type>\):\1super\2:'

Here, since the look-behind and look-ahead are constant, you could even do a simple string replacement.

sed 's:<Type>default</Type>:<Type>super</Type>:'
0

I do not really understand clearly which parts of the input are variable and which are constant. Supposing Type is variable and default, super are constants, you can use the following sed script

s:<\([^>]\+\)>default</\1>:<\1>super</\1>:
enzotib
  • 51,661