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.

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>
share|improve this question
    
Can you clarify the input you have and the output you expect? You know that (, ) and ? have no special meaning in sed if not escaped. –  enzotib Nov 10 '11 at 7:57
    
Input: <Type>default</Type>, expected output: <Type>super</Type>. I have to escape my parentheses? Why? –  Naftuli Tzvi Kay Nov 10 '11 at 7:59
    
So why do you put (?<= in the pattern if this is not present in the input? –  enzotib Nov 10 '11 at 8:15
    
Positive lookbehind? Make sure that <Type> matches before the expression? –  Naftuli Tzvi Kay Nov 10 '11 at 8:18

3 Answers 3

up vote 2 down vote accepted

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.

share|improve this answer
    
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 9:14
    
Thank you! You understood what I was trying to do :) That's EXACTLY what I meant! –  Naftuli Tzvi Kay Nov 10 '11 at 9:27

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>:'
share|improve this answer

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>:
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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