Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Regex for replacing multiple nested matches

by Lana (Beadle)
on Sep 10, 2015 at 18:17 UTC ( [id://1141585]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks!

First of all, sorry for the kind of dumb question, but I stuck with it. Maybe there something wrong with planet positions in the sky today. :) (jk)

Well, here is a code:

my $string = 'some text ###RAND{1a|###RAND{2a|2b|2c|###RAND{3a|3b|3c|3 +d}|2d}|1b|1c|1d} some text'; print process_rands($string)."\n"; sub process_rands { my $sentence = shift; my $count = () = $sentence =~ /###RAND/g; for (1..$count){ $sentence =~ s!.*###RAND\{([^\}]+)\}!get_rand_arr_el(sp +lit(/\|/,$1))!eg; print $sentence."\n"; } return $sentence; } sub get_rand_arr_el { my @array = @_; my $randomelement = $array[ rand @array ]; return $randomelement; }

The $string contains three text arrays like ###RAND{a|b|c|d} nested into each other. The a-b-c-d is a text array splitted by a pipe. What I need is process all occurences of the ###RAND{a|b|c|d} arrays in $count passes starting from the last one and moving to the first - to avoid interfering ###RAND{a|b|c|d} vars. Each pass must substitute ###RAND{a|b|c|d} with random element from the a|b|c|d array. As in this example there three nested ###RAND{a|b|c|d} text arrays, the steps should look like this:

some text ###RAND{1a|###RAND{2a|2b|2c|###RAND{3a|3b|3c|3d}|2d}|1b|1c|1 +d} some text some text ###RAND{1a|###RAND{2a|2b|2c|3b|2d}|1b|1c|1d} some text some text ###RAND{1a|2d|1b|1c|1d} some text some text 1c some text

How to make the regexp to substitute only the last occurence in each pass?

Thank you!
Lana

Replies are listed 'Best First'.
Re: Regex for replacing multiple nested matches
by clueless newbie (Curate) on Sep 10, 2015 at 19:00 UTC
    Change this [^\}] to this [^{}].
      Thank you! But seems like you have misunderstood what [^\}] does in the ###RAND\{([^\}]+)\} - it means 'anything but right curly brace' which is right, because I need everything from the curly braces of the ###RAND{3a|3b|3c|3d} written to the $1
        You don't need to escape the } within a bracketed character class. You do need not to accept any opening { within your bracketed character class.
        use Data::Dumper; my $string = 'some text ###RAND{1a|###RAND{2a|2b|2c|###RAND{3a|3b|3c|3 +d}|2d}|1b|1c|1d} some text'; print process_rands($string)."\n"; sub process_rands { my $sentence = shift; while (1) { last unless $sentence =~ s!###RAND\{([^{}]+)\}!get_rand_arr_ +el($1)!e; print $sentence."\n"; } return $sentence; } sub get_rand_arr_el { warn Data::Dumper->Dump([\@_],[qw(*_)]),' '; my @array = split '\|',$_[0]; my $randomelement = $array[ rand @array ]; return $randomelement; }
        yields
        @_ = ( '3a|3b|3c|3d' ); at play.pl line 18. some text ###RAND{1a|###RAND{2a|2b|2c|3c|2d}|1b|1c|1d} some text @_ = ( '2a|2b|2c|3c|2d' ); at play.pl line 18. some text ###RAND{1a|2b|1b|1c|1d} some text @_ = ( '1a|2b|1b|1c|1d' ); at play.pl line 18. some text 1d some text some text 1d some text
Re: Regex for replacing multiple nested matches
by BillKSmith (Monsignor) on Sep 11, 2015 at 13:02 UTC
    Frequently, the easiest way to process the end of a string first is to reverse the string (and the pattern). You may have to reverse it again when you are done.
    Bill
Re: Regex for replacing multiple nested matches
by clueless newbie (Curate) on Sep 10, 2015 at 18:59 UTC
    Change this ^\} to this ^{}. Please delete as I messed up the formatting. See below.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-04-23 06:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found