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

Kind, Gentle Folk,

Okay, I am making a rookie mistake, but I can't figure out how to work around it. I am employing the "use Getopt::Long;" module to process command-line arguments. One of the arguments is a string, and it can include regular expressions. Here is a simple example:-

$NetPattern = "mbist[\w+\d+\/]*\[\d+\]";

But when I try to compare that pattern to another variable like so...

if ($NetName =~ qr/$NetPattern/x) {# Do fantastical things...}

...and $NetName is "top_level/mbist_wrapper_pix2d[22]" the compare fails. If a user enters a command-line regular expression that gets pushed into a variable, what is the most reliable way to use that variable to compare it against another variable that is a string?

Thanks,

Fiddler42

Replies are listed 'Best First'.
Re: Comparing two variables when one variable includes a regexp...
by jettero (Monsignor) on May 01, 2008 at 15:04 UTC
    Your problem appears to be that $NetPattern doesn't contain the slashes you think it does. You have two choices:
    $NetPattern = qr{mbist[\w+\d+\/]*\[\d+\]}x; if ($NetName =~ $NetPattern) {# Do fantastical things...}
    $NetPattern = 'mbist[\w+\d+\/]*\[\d+\]'; if ($NetName =~ qr/$NetPattern/x) {# Do fantastical things...}

    The "" style quotes interpolated your slashes away.

    The qr is also most useful (in my opinion) for precompiling regular expressions, so I would choose the first solution, particularly if you have a lot of matches to do on that single regular expression. It's also nice for being able to tell that $NetPattern is of type Regexp. So, I guess there's also this third choice...

    $NetPattern = 'mbist[\w+\d+\/]*\[\d+\]'; if ($NetName =~ m/$NetPattern/x) {# Do fantastical things...}

    -Paul

      Surely all these replies that fix one example out of an infinite number of possible user inputs are missing the point?

      If I understood the original post, $NetPattern is to be read from the command line, so the example, mistaken bracketing and all, was just an example. The question was

      If a user enters a command-line regular expression that gets pushed into a variable, what is the most reliable way to use that variable to compare it against another variable that is a string?

      In our answers, we should be explaining how to validate a user-supplied string before interpolating it into a regex. A simple error like [ without matching ] is the least of our worries.

        That's an excellent point actually. I'll amend my answer, although I covered it somewhat. Assuming you actually trust the user, this seems like a sane way to do it.
        my $regexp = <$file_handle>; my $creg = eval { qr($regexp) }; if( $@ ) { warn "regex error: $@"; } else { if( $something =~ $creg ) { # do wonderful things. } }

        I apparently skipped the meat of the question because it seemed clear to me that the reason the matching failed was because of an interpolation problem with a test regexp that he generated between quotes and he wasn't actually reading it from the user -- which would have likely worked the way he had it.

        -Paul

Re: Comparing two variables when one variable includes a regexp...
by toolic (Bishop) on May 01, 2008 at 15:30 UTC
    Did you use warnings;? When I do, I get warning messages:
    Unrecognized escape \w passed through at ./683940.pl line 6. Unrecognized escape \d passed through at ./683940.pl line 6. Unrecognized escape \d passed through at ./683940.pl line 6.

    This is my version of your code:

    #!/usr/bin/env perl use warnings; use strict; my $NetName = 'top_level/mbist_wrapper_pix2d[22]'; my $NetPattern = "mbist[\w+\d+\/]*\[\d+\]"; if ($NetName =~ qr/$NetPattern/x) { print "match\n"; } else{ print "no match\n"; }

    One solution is to avoid interpolation (as jettero has already mentioned).

    #!/usr/bin/env perl use warnings; use strict; my $NetName = 'top_level/mbist_wrapper_pix2d[22]'; my $NetPattern = 'mbist[\w+\d+\/]*\[\d+\]'; if ($NetName =~ qr/$NetPattern/x) { print "match\n"; } else{ print "no match\n"; }
Re: Comparing two variables when one variable includes a regexp...
by Anonymous Monk on May 01, 2008 at 17:21 UTC
    Also note that in the regex set expression  [\w+\d+\/] the \d component is redundant because \w includes \d (the digits
    [0-9]). Furthermore, the expression  [\w+\d+\/] contains the character '+' twice, a redundancy that may lead the casual reader to think this character is a quantifier associated with the \w or \d subsets. (Also, the '/' in this set does not have to be escaped.)

    So...

    perl -wMstrict -e "my $NetPattern = 'mbist [\w/+]* \[ \d+ \]'; my $NetName = 'top_level/mbist_wrapper_pix2d[22]'; if ($NetName =~ qr/$NetPattern/x) { print 'match' } " match

    Or perhaps better yet...

    perl -wMstrict -e "my $NetPattern = qr{mbist [\w/+]* \[ \d+ \]}xms; my $NetName = 'top_level/mbist_wrapper_pix2d[22]'; if ($NetName =~ $NetPattern) { print 'match' } " match