3

I was going through examples and questions on the web related to finding and replacing a text between two strings (say START and END) using perl. And I was successful in doing that with the provided solutions. In this case my START and END are also inclusive to replacement text. The syntax I used was s/START(.*?)END/replace_text/s to replace multiple lines between START and END but stop replacing when first occurrence of END is hit.

But I would like to know how to replace a text between START and END excluding END like this in perl only.

Before:

START
I am learning patten matching.
I am using perl.
END

After:

Successfully replaced.
END

4 Answers 4

6

To perform the check but avoid matching the characters you can use positive look ahead:

s/START.*?(?=END)/replace_text/s
Sign up to request clarification or add additional context in comments.

Comments

3

One solution is to capture the END and use it in the replacement text.

s/START(.*?)(END)/replace_text$2/s

Comments

2

Another option is using range operator .. to ignore every line of input until you find the end marker of a block, then output the replace string and end marker:

#!/usr/bin/perl

use strict;
use warnings;

my $rep_str = 'Successfully replaced.';

while (<>) {
    my $switch = m/^START/ .. /^END/;
    print unless $switch;
    print "$rep_str\n$_" if $switch =~ m/E0$/;
}

It is quite easy to adapt it to work for an array of string:

foreach (@strings) {
     my $switch = ...
     ...
}

1 Comment

@IlmariKaronen Another print is needed, because there may be other lines outside those START .. END block. That feature is part of my Perl template, I forget to remove it when I paste that code. Thank you for pointed out the flaws in my answer.
1

To use look-around assertions you need to redefine the input record separator ($/) (see perlvar), perhaps to slurp the while file into memory. To avoid this, the range ("flip-flop") operator is quite useful:

while (<>) {
    if (/^START/../^END/) {
        next unless m{^END};
        print "substituted_text\n";
        print;
    }
    else {
        print;
    }
}

The above preserves any lines in the output that precede or follow the START/END block.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.