Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Iterating over code embeded in regex

by eibwen (Friar)
on Jun 13, 2006 at 03:30 UTC ( #554941=perlquestion: print w/replies, xml ) Need Help??
eibwen has asked for the wisdom of the Perl Monks concerning the following question:

I'd like to run a few lines of code on each instance of a string of a particular form. To accomplish this I've been using a regex of the form:

$s =~ /(string)(?{ print $^N, $/; })(?!)/;

While this works to print all occurances of the string in question (see Global Regex sans //g), I cannot seem to get this to work in list (or perhaps array) context:

my @letters = ('a'..'z'); for my $letter (0..$#letters) { $letters[$letter] =~ /(?{ print $letter })(?!)/; }

The code seems to run each iteration; however instead of printing the current value of $letter, it returns the following error:

Use of uninitialized value in print at (re_eval 1) line 1.

As I type this I wonder if the regex and the embeded code are being compiled prior to the instantion of the variable? I tried running it through Deparse, but it appeared to be more or less unaltered. Should this be the case, I'd surmise it happens afterwards -- perhaps at runtime?

How can I print the current value of the iteration from within the regex -- preferrably sans eval?

Replies are listed 'Best First'.
Re: Iterating over code embeded in regex
by ikegami (Pope) on Jun 13, 2006 at 03:47 UTC

    Don't use lexicals in code embedded in regexp. Use package variables.

    my @letters = ('a'..'z'); for our $letter (0..$#letters) { $letters[$letter] =~ /(?{ print $letter })(?!)/; }
Re: Iterating over code embeded in regex
by Samy_rio (Vicar) on Jun 13, 2006 at 04:01 UTC

    Hi eibwen, Try like this,

    use strict; use warnings; my @letters = ('a'..'z'); for (0..$#letters) { $letters[$_] =~ m/(?{ print $_ })(?!)/; }

    Velusamy R.

    eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

Re: Iterating over code embeded in regex
by ioannis (Prior) on Jun 13, 2006 at 05:34 UTC
    The snippet bellow shows that the $l inside the embedded code of the regex is a closure.

    use Scalar::Util 'refaddr'; for my $l ('a'..'b') { print 'loop variable ', refaddr \$l; $l =~ /(?{ print refaddr(\$l) }) /x; }

    Here is the output:

    loop variable 135603848 135606104 loop variable 135606092 135606104
Re: Iterating over code embeded in regex
by ambrus (Abbot) on Jun 13, 2006 at 12:31 UTC

    I think you shouldn't use the (?{...}) construct without a very good reason. To run some code on all matches of a regexp in a string, you can do this for example (untested):

    while ($string =~ /(pattern)/g) { do_something_with($1); }
    Or, if you want overlapping matches too, then
    while ($string =~ /(?=(patter))/g) { do_something_with($1); }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://554941]
Approved by Samy_rio
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2016-09-29 23:57 GMT
Find Nodes?
    Voting Booth?
    Extraterrestrials haven't visited the Earth yet because:

    Results (562 votes). Check out past polls.