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

need a regular exdpression in perl

by praveenchappa (Acolyte)
on Nov 20, 2014 at 07:40 UTC ( [id://1107885]=perlquestion: print w/replies, xml ) Need Help??

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

i had a string which has a pattern @begin...@end , i need to replace each occurance with an element in an array @replace....Help me out

$string=" hi hello @begintobe replace @end asas x x x x x zxzxax hi hello hi hellooo @beginthis has tobe replaced @end" ..... i had @replace=["replacestring1","replacestring2"....] i need to have my string like. $string=" hi hello @begin replacestrinjg1 @end asas x x x x x zxzxax hi hello hi hellooo @begin replacestring2 @end" .....

Replies are listed 'Best First'.
Re: need a regular exdpression in perl
by Loops (Curate) on Nov 20, 2014 at 08:24 UTC

    Your source string needs to be in single quotes, otherwise Perl will try to interpolate '@begin' and '@end' as arrays. You also don't want to put your replacement strings inside square brackets, that groups them as a single array reference inside of @replace, rather than as individual strings.

    Anyway, this should get you started:

    use strict; use warnings; my $string=' hi hello @begintobe replace @end asas x x x x x zxzxax hi hello hi hellooo @beginthis has tobe replaced @end ...'; my @replace= ("replacestring1","replacestring2"); $string =~ s|\@begin.*?\@end |shift @replace // '[null]' |sexg; print $string;

    Usually regular expression substitutions are written as:

    s/<pattern>/<substitution text>/<modifiers>

    But in my code above, the vertical bar (or pipe) symbol (|) is used instead. It's also split over 3 lines which is allowed when you use the "x" modifier.

    The "e" modifier means that instead of substitution text, the given code will be executed for each @begin ... @end match. The code shown, removes the first element of the array and returns it for the current substitution. If the @array becomes empty, the literal value '[null]' will be used instead.

    The "g" modifier causes the substitution to be done as many times as there are matches found in the string -- consuming another array element each time. Without it only the first substitution would be done.

    And lastly the "s" modifier means that the period character in the pattern, will match newline characters since those appear in your example input string.

    Much more information can be found in the perlre and perlretut documentation.

      Slightly off-topic, but when writing such a templating engine, I prefer to deal with missing replacement values by leaving the template parameters as-is (that is, replacing the template parameter by itself instead of a (missing) value):

      $string =~ s|(\@begin.*?\@end) |shift @replace // 'Missing parameter for ' . $1 |sexg;

      I find this helps me debug the template better, as I easily see which template expression failed. This still does not help me see why a value was missing, but at least I know where the value was missing.

Re: need a regular exdpression in perl
by GrandFather (Saint) on Nov 20, 2014 at 08:07 UTC
Re: need a regular exdpression in perl
by Eily (Monsignor) on Nov 20, 2014 at 08:08 UTC

    That's your second post on the subject (the first here), so by now you should have some code. Go on and try something, and present some runnable code that fails to do what you want, and then you can ask for advice. But just don't expect perlmonks to magically sprout whatever solution you need without any visible effort on your side.

Re: need a regular exdpression in perl
by Corion (Patriarch) on Nov 20, 2014 at 08:09 UTC

    What code have you written and where do you have problems with it?

    How does your code fail?

    Have you looked at using one of the established template modules instead of rolling your own template?

Re: need a regular exdpression in perl
by Anonymous Monk on Nov 20, 2014 at 08:13 UTC

    i had a string which has a pattern @begin...@end ,...

    you don't have it anymore because double strings interpolate... you should post an actual short perl program, perlintro can help you get started, this is the beginning where you have to start

Re: need a regular exdpression in perl
by AnomalousMonk (Archbishop) on Nov 20, 2014 at 14:57 UTC

    Here's another approach. This needs Perl version 5.10+ for  \K (if you have < 5.10, let me know; I can supply adjusted code).

    c:\@Work\Perl>perl -wMstrict -le "use 5.010; ;; my $s = qq{xxx \@B grab \n this \@E yy zzzz \@B and \n this \n too \@ +E qq}; print qq{[[$s]]}; ;; my $start = qr{ \@B }xms; my $stop = qr{ \@E }xms; ;; my $replace = [ 'ZOT', 'ZONK' ]; ;; my $i = 0; $s =~ s{ $start \K .*? (?= $stop) } { $replace->[ $i++ % @$replace ] }xmsg; print qq{<<$s>>}; " [[xxx @B grab this @E yy zzzz @B and this too @E qq]] <<xxx @B ZOT @E yy zzzz @B ZONK @E qq>>

    Pay particular attention to Loops's and Corion's remarks here and here about what should happen when the  $replace array is exhausted (I just wrap around and start re-using replacement strings), and also here about using a real templating engine rather than trying to roll your own.

    Update: Removed a needless capture group:  .*? vice  (.*?)

Re: need a regular exdpression in perl
by Sathishkumar (Scribe) on Nov 20, 2014 at 11:07 UTC
    Hi Praveen Try this code
    #!/usr/bin/perl use strict; use File::Find; use warnings; my @file=("hh","yy","zz","aa","bb","hh","yy","zz","aa","bb","hh","yy", +"zz","aa","bb"); my $i=0; my $string='hi hello @begintobe replace @end asas x x x x x zxzxax hi hello hi hellooo @beginthis has tobe replaced @end'; my $x=$file[$i]; while ($string =~ m/\@begin([\w\W]*?)\@end/g) { $i++; $string =~ s/\@begin([\w\W]*?)\@end/$x/s; $x=$file[$i]; print $i."\n"; } print $string;
Re: need a regular exdpression in perl
by praveenchappa (Acolyte) on Nov 20, 2014 at 08:26 UTC

    ok, my program looks as below

    #!/usr/bin/perl use strict; use File::Find; use warnings; my @file=("hh","yy","zz","aa","bb","hh","yy","zz","aa","bb","hh","yy", +"zz","aa","bb"); my $i=0; $string=" hi hello @begintobe replace @end asas x x x x x zxzxax hi hello hi hellooo @beginthis has tobe replaced @end"; my $x=$file[$i]; while ($string =~ s/\@begin([\w\W]*?)\@end/$x/ge) { $i++; $x=$file[$i]; print $i."\n"; } print $string;

    and i am getting output as below so far<\p>

    ##output hi hello hh asas x x x x x zxzxax hi hello hi hellooo hh

    only the first element in the arrray is getting replaced in every match...

      This does not even compile, and even if it did, $string does not contain either @begin or @end (try printing it without doing any replacement). Have a look at Loops's post on that point.

      If strict gives you errors (when you actually use it, and don't just put it when you update your code on perlmonks), it's nearly always a sign that the code is wrong, and doesn't mean what you expect. Same goes for warnings.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-04-26 01:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found