How do I tell sed to repeat substitution until no match was replaced?

Viewed 342

How do I tell sed to repeat substitution until no match was replaced?

If doing echo x | sed 's/x/xx/g' I'm really glad sed doesn't restart on the output.

But if I have, say, echo 'x,a,b,x,x,c,x,d,e,x,x,x,f,x' | sed 's/,x,/,y,/g' it does not substitute every x for y, for an obvious reason: the prior substitution has already consumed the surrounding delimiters.

And I'm aware that I have a tiny problem with the first and last x as well, but I ignore this for simplicity of the question.

Edit: I have to clarify the question, as already mentioned but only in comments: I want to see every x replaced by y, but only if it was a single word for itself, enclosed by delimiters, commas in this example, but if there is a way to cope with more complex delimiters, this will be welcome.

(No way to fall into the y2k trap, replacing Monday by Mondak, just joking.)

3 Answers

What about

$ echo 'x,a,b,x,x,c,x,d,e,x,x,x,f,x' | sed ':label; s/,x,/,y,/g; t label;'
x,a,b,y,y,c,y,d,e,y,y,y,f,x

? This will not replace the x at the edges but that was not requested explicitly.

It will also not replace x in words:

$ echo 'x,a,b,fix,x,c,x,d,e,x,x,x,f,x' | sed ':label; s/,x,/,y,/g; t label;'
x,a,b,fix,y,c,y,d,e,y,y,y,f,x

Explanation: the t command will jump to the label if some substition took place. It will the apply the same sed expression to the line again.

Related