Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing multiple delimited blocks in sed

Tags:

sed

I have a body of text which contains groups delimited with <>,## or ||. The blocks never overlap, but may cross multiple lines, like so:

#A fully emphasized line#
A line with #emphasis inside#.
#Several lines of
text
With emphasis#
no emphasis
Line #with# multiple #emphasis#.
Line <with some > |text of| #each type#.

I'm attempting to replace each pair of delimiters with [ and ] and put the final delimiter after the ]; for example the last line should be:

Line [with some ]> [text of]| [each type]#.

I have formed a sed script which will do the first part:

sed -e ':left s/[#|<]/[/; t right; n; b left :right s/[#|>]/]/; t left;n; b right'

But when I try to use & (or (..) + \1) to put the character back in like this:

sed -e ':left s/[#|<]/[/; t right; n; b left :right s/[#|>]/]&/; t left;n; b right'

I get the following:

[A fully emphasized line][
A line with ][emphasis inside][.
][Several lines of
text
With emphasis][
no emphasis
Line ][with][ multiple ][emphasis][.
Line [with some ]]]]]]> [text of[ [each type[.

I'm not sure what has gone wrong here though - it appears to be screwing with the pattern block in some way. I could replace it with three calls (hardcoded one per match type), but that seems excessive.

like image 817
Oliver Matthews Avatar asked Oct 04 '22 12:10

Oliver Matthews


1 Answers

Try following command. It reads the whole file in memory and do global substitutions for each pair of delimiters:

sed -e '
    :a
    $! { N; ba };
    s/#\([^#]*\)#/[\1]#/g; 
    s/<\([^>]*\)>/[\1]>/g; 
    s/|\([^|]*\)|/[\1]|/g
' infile

It yields:

[A fully emphasized line]#
A line with [emphasis inside]#.
[Several lines of
text
With emphasis]#
no emphasis
Line [with]# multiple [emphasis]#.
Line [with some ]> [text of]| [each type]#.
like image 197
Birei Avatar answered Oct 10 '22 13:10

Birei