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

Hello everyone. You are all great! I have one more question : I have thousands of files and I have to perform a replace in all of them so that the example generic string:
catch [ [ commands etc ................ ] ]
will get replaced by :
catch { [ commands etc ................ ] }
There is a twist, though, the line could span 2 lines like this:
catch [ [ commands etc ................ ] \ ..... other commands and brackets ]
Could you please advise how could I get a proper regexp to perform the change throughout my files to achieve also the multi line to be transformed into:
catch { [ commands etc ................ ] \ ..... other commands and brackets }
Thanks.

Replies are listed 'Best First'.
Re: Search and Replace on multi line ability
by GrandFather (Saint) on Oct 04, 2008 at 00:18 UTC

    In general that is not really a job for a regex, it is a job for a parser. The issue is that generally it is messy to handle balanced text with regexen (not impossible with Perl regexes, but messy). If the commands were simple and it was not possible to have [, ], { or } in the 'commands etc' then the job is fairly trivial, but that is not the case.

    Your simplest option may be to roll your own simple recursive decent parser for the job. Consider:

    use strict; use warnings; while (defined (my $line = <DATA>)) { next unless $line =~ /^(catch\s*)\[(.*)/s; my $prefix = $1; my ($body, $tail) = parse ($2); $line = "${prefix}{$body}$tail"; } continue { print $line; } sub parse { my ($tail) = @_; my $outStr = ''; while (defined $tail) { if ($tail =~ s/^([^[]*)\[(.*)//s) { my $prefix = $1; my $body; ($body, $tail) = parse ($2); $outStr .= "$prefix [$body]"; next if length $tail; } elsif ($tail =~ s/^([^\]]*)](.*)//s) { return "$outStr$1", $2; } $outStr .= $tail; $tail = <DATA>; } return $outStr, ''; } __DATA__ catch [ this; that; the; other; ] some random stuff that isn't a catch catch [ this[]; that + 1; the other; ]

    Prints:

    catch { this; that; the; other; } some random stuff that isn't a catch catch { this []; that + 1; the other; }

    although there are likely to be many special cases (quoted or commented unbalanced brackets for example) that mean that a heavier duty parser like Parse::RecDecent may be what you really need.


    Perl reduces RSI - it saves typing
      I agree with you, I am going for the parser approach. Sincerely, Thanks.
Re: Search and Replace on multi line ability
by ikegami (Patriarch) on Oct 03, 2008 at 23:28 UTC
Re: Search and Replace on multi line ability
by NetWallah (Canon) on Oct 03, 2008 at 23:42 UTC