Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Substitution with matching nested boundary conditions

by redhotpenguin (Deacon)
on Jan 24, 2008 at 22:00 UTC ( [id://664150]=perlquestion: print w/replies, xml ) Need Help??

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

Monks,

I'm trying to solve a difficult (for me at least) regex substitution problem. I think part of the issue is I am trying to use a regex where a short parser implementation would be more appropriate, but I'm Lazy, and hoping that I can coerce Perl's regex engine into doing the work for me. Onto the problem at hand (please ignore whitespace inconsistencies in the content).

my $content = <<CONTENT; foo somestuff zimzam someotherstuff bar evenmorestuff foo bar zimzam foo zimzam bar CONTENT my $orig_zimzam = 'zimzam'; my $rep_zimzam = 'zoomzam'; $content =~ s/(foo(?!bar).*?)\Q$orig_zimzam\E(.*?bar)/$1$rep_zimzam$2/ +sg; print $content;

The regex I have in this post is one of many variations that I've tried, but this content test case seems to foil all of them. I've used use re 'debug' to look at the inner goodness of what's going on with the regex, but I am coming up empty.

In short, I'm trying to replace all instances of zimam nested between foo and bar, with zoomzam. Strange names, but I've boiled the bigger problem down to a test case here that fails. Here's the current output.

foo somestuff zoomzam someotherstuff bar evenmorestuff foo bar zoomzam foo zimzam bar

And the expected output

foo somestuff zoomzam someotherstuff bar evenmorestuff foo bar zimzam foo zoomzam bar

Any ideas? (some whitespace formatting is incorrect, please ignore it)

Replies are listed 'Best First'.
Re: Substitution with matching nested boundary conditions
by dave_the_m (Monsignor) on Jan 24, 2008 at 22:41 UTC
    This seems to do the trick:
    $content =~ s{(foo.*?bar)}{ my $s = $1; $s =~ s{\Q$orig_zimzam\E}{$rep_zimzam}; $s; }sge;

    Dave.

Re: Substitution with matching nested boundary conditions
by graff (Chancellor) on Jan 25, 2008 at 06:08 UTC
    What's supposed to happen when "zimzam" occurs more than once within a given "foo ... bar" span? Note that the excellent solution provided by dave_the_m would only replace the first occurrence in that case, but just add a "g" modifier on the "inner" s/// operation to make it apply to all occurrences of "zimzam" within the captured "foo...bar" range.
      It should be replaced in all occurrences. I actually ran into that, and added the g modifier, and it worked great.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://664150]
Approved by grep
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-03-29 13:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found