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

What is the correct syntax for matching a constant in a regular expression? Here's the culprit:
#!/usr/bin/perl; use constant EXTENSION => '.txt'; die sprintf( 'cannot match "%s" extension in "%s"', EXTENSION, $ARGV[0] ) unless $ARGV[0] =~ /EXTENSION$/;
Thanks for your help.

Replies are listed 'Best First'.
Re: constants within regular expression?
by davido (Cardinal) on Nov 26, 2003 at 06:20 UTC
    Constants aren't interpolated as such inside quotes or regexp quote-like m// expressions. Inside the m// expression, the text that you're using as the name of a constant is actually just seen as literal text to match.

    This is documented in the POD for the 'constant' pragma:

    Constants defined using this module cannot be interpolated into strings like variables.

    You can work around that behavior like this:

    use constant MYTEST => '.txt'; my $expression = quotemeta( MYTEST ); my $string = "test.txt"; if ( $string =~ /$expression/ ) { print "Match\n"; }


    Dave


    "If I had my life to live over again, I'd be a plumber." -- Albert Einstein

      Another WTDI:

      print "Match" if $string =~ /@{[MYTEST]}/;
        @{[MYTEST]} leaves out the all-important "quotemeta". In the OP's example, the literal text to match against was ".txt", and without quotemeta, '.' will match anything, instead of dot.


        Dave


        "If I had my life to live over again, I'd be a plumber." -- Albert Einstein
        Thanks folks! This gives me a number of different ways to solve the problem.
Re: constants within regular expression?
by perrin (Chancellor) on Nov 26, 2003 at 06:36 UTC
    As other have explained, constants are just subroutines. This is why I tell people they'd be better off using normal variables for their constants. The speed gain from in-lining is not worth being bitten by all the different ways that they fail.
Re: constants within regular expression?
by edan (Curate) on Nov 26, 2003 at 09:10 UTC
Re: constants within regular expression?
by Coruscate (Sexton) on Nov 26, 2003 at 06:27 UTC

    Constants are transformed into subroutines (at least in some cases, I'm not too familiar with them at all). So one possibility of what to do is get a subroutine call inside your regex. Looking at the perldocs for constant and perlre, I came up with this working code. It uses a highly experimental regex feature, so you probably won't want to use this. Take a look at the perlre documentation to learn more about what the (??{}) construct does. It worked for me, so here it is.

    #!/usr/bin/perl -w $|++; use strict; use constant EXTENSION => '.txt'; my $file = shift; die sprintf( 'cannot match "%s" extension in "%s"', EXTENSION, $file ) unless $file =~ /(??{EXTENSION()})\z/;

    Update: I figure I'd cross this out just because you really don't want to use an experimental feature, do you? As discovered with the help of Zed_Lopez, you should really use something like this regex snippet. Or, follow perrin's advice and just use variables instead of constants :)

      Constants are transformed into subroutines (at least in some cases, I'm not too familiar with them at all).

      Constants created with constant.pm are indeed subs (in all cases.) They are made by aliasing the constant's name to an anonymous sub with an empty prototype the body of which is simply the supplied value. The empty prototype is a hint to perl that the sub is a candidate for inlining. In other words, you could create your own "constants" with code like

      sub MY_CONSTANT () { 42 }
      if you wanted.

      -sauoq
      "My two cents aren't worth a dime.";
      

        i don't know what the empty prototype implies for inlining, but it also keeps the sub from swallowing arguments.

        sub A () {1}; sub B {2}; print A + 1,$/; print B + 1,$/; __END__ prompt$ perl test.pl 2 2prompt$

        without the empty prototype subs wouldn't work very well for constants.