Sed seems to replace only the last occurrence in g

2019-05-24 12:56发布

问题:

I use this command, but it's not working ad intended:

echo "0+223+141+800+450+1*(106+400)+1*(1822+500)+1*(183+400)" | sed 's/\*\(.*\)+/*\1suma/g'

This is the expected output:

0+223+141+800+450+1*(106suma400)+1*(1822suma500)+1*(183suma400)

but this is what I get:

0+223+141+800+450+1*(106+400)+1*(1822+500)+1*(183suma400)

It looks like only the last occurrence is being replaced, despite the use of g.

回答1:

Try the following:

echo "0+223+141+800+450+1*(106+400)+1*(1822+500)+1*(183+400)" |
    sed 's/\(\*([^+]*\)+/\1suma/g'

which yields:

0+223+141+800+450+1*(106suma400)+1*(1822suma500)+1*(183suma400)

The trick is to avoid sed's invariably greedy matching, so expression [^+]* is used instead of .*, so as to only match up to the next +.


Note that your attempt didn't only replace the last occurrence of your intended pattern, but - due to greedy matching - found only 1 match spanning multiple intended patterns, which it replaced:

\*\(.*\)+ matched *(106+400)+1*(1822+500)+1*(183+ - everything from the first * literal to the last + literal, and capture group \1 therefore expanded to (106+400)+1*(1822+500)+1*(183