Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

calling regular expressions returned by functions?

by Anonymous Monk
on Mar 29, 2012 at 18:14 UTC ( [id://962450]=perlquestion: print w/replies, xml ) Need Help??

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

Hey, monks!

I have a number of repeated regular expressions used throughout some code, and it would be good if they were consolidated. Below is some code which illustrates what I am trying to do:

#!/bin/env perl use strict; use warnings; use Data::Dumper; #use constant DOT => qr/^\.$/; #use constant DOT_DOT => qr/^\.\.$/; opendir(my $dh, '.'); my @lst = grep { !/^\.$/ && !/^\.\.$/ } readdir($dh); #my @lst = grep { !DOT && !DOT_DOT } readdir($dh); print Data::Dumper->Dump([\@lst], [qw/lst/]);

As you can surmise from what is commented out, I am trying to move the regular expressions to constants, but I haven't mastered the syntax. How can I use constants within regular expressions? Your insight would be greatly appreciated!

Thanks!

Replies are listed 'Best First'.
Re: calling regular expressions returned by functions?
by AnomalousMonk (Archbishop) on Mar 29, 2012 at 19:07 UTC

    The problem is that  m// binds by default to  $_ in the absence of an explicit binding, e.g.,  $s =~ m{pattern}; A poor, naked  qr// doesn't know what to bind to and must always be bound explicitly as BrowserUk has done.

    In general, the interpolation of a constant into a regex is messy:
        use constant FOO => qr{ foo }xms;
        print 'got foo' if 'foo' =~ m{ @{[ FOO ]} }xms;

    The use of a Readonly constant makes things neater:
        use Readonly;
        Readonly my $FOO => qr{ foo }xms;
        print 'got foo' if 'foo' =~ m{ $FOO }xms;
    but BrowserUk will tell you that the Readonly module has some dirty little secrets of its own. YMMV.

      Ah! This is where I blundered; I didn't understand regex binding.

      Thank you all for your patience & taking the time to share your insight. This will help me write more robust code.

Re: calling regular expressions returned by functions?
by BrowserUk (Patriarch) on Mar 29, 2012 at 18:36 UTC

    Its not pretty, but this works:

    use constant DOT => qr[\.];; print grep $_ =~ DOT, qw[ a b c . d e f];; .

    Though it is really hard to see the benefit of making constants of those particular regex.

    It's not like they are going to change anytime soon, and if they did, then you'd want to change their names also, which means you'd have to edit the place of use as well anyway.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      Agreed as far as the directory semantics staying the same.

      However, the question is larger than just directory filtering. What constants gain is lessening the chance that a regular expression gets changed in one location when it needs to be changed in all locations, or it gets changed incorrectly in a code branch which isn't executed often or unfortunately tested. I only used directory filtering as an example.

      Thanks for your contribution.

Re: calling regular expressions returned by functions?
by toolic (Bishop) on Mar 29, 2012 at 18:30 UTC
    I realize this doesn't answer your question directly, but File::Slurp::read_dir automatically excludes the dot dirs for you. This is equivalent to your code:
    use warnings; use strict; use Data::Dumper; use File::Slurp; my @lst = read_dir('.'); print Data::Dumper->Dump([\@lst], [qw/lst/]);

      Thanks! That is good to know.

      However, I'm most interested in figuring out the syntax needed to move regular expressions to constants. My Perl foo is weak.

      Thanks, again for responding. Maybe my foo isn't quite as weak now...

Re: calling regular expressions returned by functions?
by wallisds (Beadle) on Mar 29, 2012 at 19:03 UTC

    1. Define a variable holding the regex you want to use.
      • my $dot = qr/^[^\.{1,2}]/;
      • This checks to see if the string begins with a period or two (.) or (..)
    2. Check out http://perldoc.perl.org/functions/our.html
    3. for more info... about 'our' and 'my' for defining variables. In your example - my will work fine.
    4. Use your defined variables in the grep, shown below.
    Happy grepping, Dawn

    my @list = qw(. .. test.xls file100.pl); my $dot = qr/^[^\.{1,2}]/; my @files = grep { /$dot/ } @list; foreach my $file(@files) { print "$item\n"; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-04-18 04:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found