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

I would like create regular expression from command line arguments. I want the regular expression to use logical AND for all the expressions. This is the code I have so far:
# build regular expression from command line args my $re; foreach my $arg (0 .. $#ARGV){ if($arg == $#ARGV){ $re .= "/(\\x01.?$ARGV[$arg].?\\x01)/"; }else{ $re .= "/(\\x01.?$ARGV[$arg].?\\x01)/&&"; } } while (<STDIN>){ if($re){ print "$_\n"; } } print "equivalent grep: grep -P \"$re\"\n";

Replies are listed 'Best First'.
Re: creating regular expressions dynamically from the command line
by kennethk (Abbot) on Dec 14, 2010 at 20:14 UTC
    The posted code is building a string, and hence since a non-empty string tests true, your code will always output. Since you want to join your regular expressions with an 'and', the simplest implementation (IMHO) would be using Perl to handle the conditional logic. What you've written so far would be most naturally converted to an eval, but it seems more logical to simply use the qr// delimiter (see Regexp Quote Like Operators in perlop) to stash them all in an array, and then track test success with a flag, perhaps like:

    #!/usr/bin/perl use strict; use warnings; # build regular expression from command line args my @res; foreach my $arg (@ARGV) { push @res, qr/$arg/; } while (<STDIN>){ my $fail = 0; foreach my $re (@res) { $fail ||= $_ !~ $re; } print unless $fail; }
Re: creating regular expressions dynamically from the command line
by planetscape (Chancellor) on Dec 14, 2010 at 20:41 UTC
Re: creating regular expressions dynamically from the command line
by AnomalousMonk (Archbishop) on Dec 15, 2010 at 11:18 UTC

    Something like one of the approaches mentioned above is probably best, but if you want to roll your own regex, here's a way. The standard caution about metaquoting the strings that are used to make the regex if they might contain metacharacters applies.

    >perl -wMstrict -le "my @anded = qw(foo bar baz); ;; my $jumbled = join ') (?= .*? ', @anded; $jumbled = qr{ \A (?= .*? $jumbled) }xms; print qq{any order: $jumbled}; ;; my $ordered = join ') .*? (?: ', @anded; $ordered = qr{ (?: $ordered) }xms; print qq{sequential: $ordered}; ;; while (<>) { chomp; print qq{string: '$_'}; print /$jumbled/ ? ' ' : 'no', ' match jumbled'; print /$ordered/ ? ' ' : 'no', ' match ordered'; print ''; } " any order: (?msx-i: \A (?= .*? foo) (?= .*? bar) (?= .*? baz) ) sequential: (?msx-i: (?: foo) .*? (?: bar) .*? (?: baz) ) "foo " string: '"foo "' no match jumbled no match ordered "foo bar ba" string: '"foo bar ba"' no match jumbled no match ordered "foo bar baz" string: '"foo bar baz"' match jumbled match ordered "baz foo bar" string: '"baz foo bar"' match jumbled no match ordered ^Z