Gerard has asked for the wisdom of the Perl Monks concerning the following question:

I have a whole lot of source text files that I need to remove a particular section from. First of all I should point out that I am not much good at regular expressions.
Anyway here is an example of the section I need to remove
onValidate { stuff in here }
What I have come up with,
$text=~s/onValidate\s{(.*?)}//g;
Should match ok, but it is possible that the section could look like
onValidate { stuff in here { other stuff } }
How would I go about matching to the last } ? Given that there are also plenty of other { } in the file which I do not want to match. Also, will this replace multiple times in the file, provided I read the whole file into $text?

Thanks, Gerard

Replies are listed 'Best First'.
Re: pattern matching nested { }'s
by Caron (Friar) on Mar 02, 2004 at 10:06 UTC

    Using Regexp::Common you should do this quite easily.

    #!/usr/bin/perl -w use strict; use Regexp::Common; my $text = <<TEXT; onValidate { stuff in here { other stuff } } keep this { remove this {and {this}} } TEXT $text =~ s/$RE{balanced}{-parens=>'{}'}//g; print $text;

    It will print:

       onValidate
    
       keep this
    
    

    Update [1] If you'd rather do this without a module, you can try this regular expression:

    our $re = qr/(?:\{(?:(?>[^\{\}]+)|(??{$re}))*\})/;
    (I am not a RegEx guru. I got it by just printing $RE{balanced}{-parens=>'{}'} and adjusting it a bit.)

    Update [2] And to explain how all this works, here goes:

    use YAPE::Regex::Explain; print YAPE::Regex::Explain->new($re)->explain;

      Thanks for your reply. I think I was a little unclear in my original post. Only the { } immediately after onValidate should match. For example:
      onValidate { stuff in here { other stuff } }
      should all be removed and
      keep this { remove this {and {this}} }
      should all be kept.

      Thanks, Gerard.

        Well, in that case, just say it to your replacement command:

        $text =~ s/(onValidate)\s*$re/$1/g; # or even $text =~ s/(?<=onValidate)\s*$re//g; print $text;

        It gives:

           onValidate
           keep this
           {
               remove this {and {this}}
           }
        
Re: pattern matching nested { }'s
by diotalevi (Canon) on Mar 02, 2004 at 14:29 UTC
Re: pattern matching nested { }'s
by bart (Canon) on Mar 02, 2004 at 21:09 UTC
    If your text looks remotely like Perl, then Text::Balanced is worth a look. That module used to be part of the Parse::RecDescent distribution — it takes care of extracting the "Perl rules code" out of the grammars — but now it is a separate distribution.
    #!/usr/bin/perl use Text::Balanced 'extract_bracketed'; $_ = <<'#END#'; This stays onValidate { stuff in here { other stuff } } This stays too #END# if(/onValidate/) { print substr($_, 0, $-[0]); # before my ($extracted, $remainder) = extract_bracketed(substr($_, $+[0]), + '{}'); print $remainder; # after print "\n## extracted: ##\n$extracted\n"; }
    which produces:
    This stays
    
    
    
    This stays too
    
    ## extracted: ##
    {
        stuff in here
        {
           other stuff
        }
       }