You could construct a single regex that would work IF the arguments were not regex expressions.
The idea is the following sequence:
- an alternation
(one|two|...)
- followed by non-greedy anything
(.*?)
- followed by a negative lookahead of what matched alternation #1
(?!\1)
- followed by the repeated alternation
(one|two|...)
- followed by non-greedy anything
(.*?)
- followed by a negative lookahead of an alternation of what matched either of the last alternations
(?!\1|\2)
Repeat 4-6, until we have a match for all terms.
So the code that constructs this is:
sub create_compound_match {
my @args = @_;
my $arg_limit = $#args;
my $expr = join( '|', map { lc; } @args );
my $neg_lookahead = join( '|', map { "\\$_" } 1..$arg_limit );
my $test = join( '.*?'
, "($expr)"
, ( map { '(?!'
. substr( $neg_lookahead, 0, 3 * $_ - 1 )
. ")($expr)"
} 1..$arg_limit
)
);
return qr/$test/i;
}
Which would be tested in this fashion:
my $test = create_compound_match( @ARGV );
print foreach grep { /$test/i } <$fh>;
However, this lacks the ability of to pass in regexes on the command line @ARGV
could equal qw, and the generated regex would happily match 'a aa aaa aaaa' without requiring the match of b*
, because "aa" != "a", so the negative lookahead is satisfied.