Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Subroutine Reference in a Regexp?

by Amblikai (Scribe)
on Nov 08, 2018 at 20:24 UTC ( #1225454=perlquestion: print w/replies, xml ) Need Help??
Amblikai has asked for the wisdom of the Perl Monks concerning the following question:

I was knocking up some code today and i figured this was an interesting question for you guys

Essentially, i was wondering if it is possible to have subroutine references/calls inside a regexp? For example, subs that return a precompiled part of the regexp?

In other words, in entirely made up Perl, is this possible?..

#!/usr/bin/perl -w my $string="more than one part\nanother sentence more than"; sub getone {return qr/(more)/;} sub gettwo {return qr/(than)/;} my @array=$string=~/(\s&getone\s&gettwo)/g;

Obviously i've tested that and its nonsense, but is there a similar approach?

Thanks!

Replies are listed 'Best First'.
Re: Subroutine Reference in a Regexp?
by haukex (Canon) on Nov 08, 2018 at 20:34 UTC

    That'd be (??{ code }) - live demo of the following (requires a modern browser; don't mind the "Subroutine redefined" warnings, I'll have to get around to fixing those):

    use warnings; use strict; my $string = "more than one part\nanother sentence more than"; sub getone { qr/more/ } sub gettwo { qr/than/ } while ( $string =~ m{( (??{getone}) \s+ (??{gettwo}) )}xg ) { print "<$1>\n"; }

      I don't know how to check that but doesn't that stringify then recompile the precompiled regexes?

        I don't know how to check that but doesn't that stringify then recompile the precompiled regexes?

        Hm, that's a good question, I'm not sure at the moment how to check either... hopefully inspiration will strike later :-)

        Your and jwkrahn's posts did remind me of a possibly important caveat: (??{...}) will re-execute the block of code every time, while interpolation will only execute it once:

        use warnings; use strict; #use re 'debug'; my $str = "foobar"; sub getit { print "Getit! pos=",pos($str)//"undef","\n"; return qr/[aeiou]/i; } print "### haukex\n"; print "Matches: <", $str=~/(??{getit})/g, ">\n"; print "### jwkrahn\n"; my $reg_str = getit(); print "Matches: <", $str=~/$reg_str/g, ">\n"; print "### Eily\n"; print "Matches: <", $str=~/@{[getit]}/g, ">\n"; __END__ ### haukex Getit! pos=0 Getit! pos=1 Getit! pos=2 Getit! pos=3 Getit! pos=4 Getit! pos=5 Getit! pos=6 Matches: <ooa> ### jwkrahn Getit! pos=undef Matches: <ooa> ### Eily Getit! pos=undef Matches: <ooa>

      Perl never ceases to amaze me!

      Thank you!

Re: Subroutine Reference in a Regexp?
by jwkrahn (Monsignor) on Nov 09, 2018 at 01:57 UTC

    You can also do it via string interpolation:

    #!/usr/bin/perl -w my $string = "more than one part\nanother sentence more than"; sub getone { qr/(more)/ } sub gettwo { qr/(than)/ } my @array = $string =~ /(\s@{[ getone() ]}\s@{[ gettwo() ]})/g;
Re: Subroutine Reference in a Regexp?
by Eily (Prior) on Nov 09, 2018 at 17:10 UTC

    There's also the more familiar options of either building the regex as a string first, or using temporary variables:

    # Temp str my $reg_str = '(\s'.getone().'\s'gettwo().')'; $str =~ /$reg_str/; # Temp scalars my $getone = getone(); my $gettwo = gettwo(); $str =~ /(\s $getone \s $gettwo )/xg;
    It's easier to understand than @{[ LIST ]} or (??{ CODE }) patterns, and probably not noticeably slower, if at all.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2018-11-19 09:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My code is most likely broken because:
















    Results (209 votes). Check out past polls.

    Notices?