The following will work even if you give it only a single line of input. The "flag" you mention is more properly referred to as a state variable.
#!/usr/bin/perl use strict; use warnings; my $retain = ""; while (<DATA>) { chomp; if (m{^(<p>)(.*)(</p>)$}) { my ($begin, $middle, $end) = ($1, $2, $3); # This line is inside a <p>...</p> match. # Handle differently if it's the first line. if (! $retain) { # Found first <p> in block, replace with <con>. # Print beginning and middle, but retain end, in case # this one line is also the end of the block. print "<con>"."$middle"; $retain = $end; } else { print "$retain\n"; # Finish off previous line print "$begin"."$middle"; # Start new line $retain = $end; # retain ending } } else { # This line is not a <p>...</p> match, # so flush preserved output, if any, # and copy this line to the output. if ($retain) { print "</con>\n"; # Finish off previous line $retain = ""; } print "$_\n"; } } if ($retain) { print "</con>\n"; # Finish off previous line } #<p>This is para2</p> #<p>This is para3</p> __DATA__ <root> <p>This is para1</p> </root>
Input cases and appropriate output:
Case 1 Input: Single line
<p>This is para1</p>
Case 1 Output:
<con>This is para1</con>
Case 2 Input: Multiple lines in block
<p>This is para1</p> <p>This is para2</p> <p>This is para3</p>
Case 2 Output:
<con>This is para1</p> <p>This is para2</p> <p>This is para3</con>
Case 3 Input: non match lines present
<root> <p>This is para1</p> <p>This is para2</p> </root>
Case 3 Output:
<root> <con>This is para1</p> <p>This is para2</con> </root>
Case 4 Input: Multiple separate blocks (I assume you want separate blocks treated separately.)
<root> <p>This is para1</p> <p>This is para2</p> </root> <stem> <p>This is para3</p> </stem>
Case 4 Output:
<root> <con>This is para1</p> <p>This is para2</con> </root> <stem> <con>This is para3</con> </stem>
In reply to Re: Set the flag
by gmargo
in thread Set the flag
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |