Reputation: 2505
I'd like a regex to match everything but a few specific options within a broader expression.
The following example will match test_foo.pl or test_bar.pl or test_baz.pl:
/test_(foo|bar|baz)\.pl/
But I'd like just the opposite:
match test_.*\.pl except for where .* = (foo|bar|baz)
I'm kind of limited in my options for this because this is not directly into a perl program, but an argument to cloc, a program that counts lines of code (that happens to be written in perl). So I'm looking for an answer that can be done in one regex, not multiple chained together.
Upvotes: 2
Views: 373
Reputation: 386331
(?:(?!STR).)*
is to
STR
as
[^CHAR]
is to
CHAR
So you want
if (/^test_(?:(?!foo|bar|baz).)*\.pl\z/s)
More readable:
my %bad = map { $_ => 1 } qw( foo bar baz );
if (/^test_(.*)\.pl\z/s && !$bad{$1})
Upvotes: 1
Reputation: 118148
#!/usr/bin/env perl
use strict; use warnings;
my $pat = qr/\Atest_.+(?<!foo|bar|baz)[.]pl\z/;
while (my $line = <DATA>) {
chomp $line;
printf "%s %s\n", $line, $line =~ $pat ? 'matches' : "doesn't match";
}
__DATA__
test_bar.pl
test_foo.pl
test_baz.pl
test baz.pl
0test_bar.pl
test_me.pl
test_me_too.txt
Output:
test_bar.pl doesn't match test_foo.pl doesn't match test_baz.pl doesn't match test baz.pl doesn't match 0test_bar.pl doesn't match test_me.pl matches test_me_too.txt doesn't match
Upvotes: 1
Reputation: 208545
You should be able to accomplish this by using a negative lookahead:
/test_(?!foo|bar|baz).*\.pl/
This will fail if foo
, bar
, or baz
immediately follows test_
.
Note that this could still match something like test_notfoo.pl
, and would fail on test_fool.pl
, if you do not want this behavior please clarify by adding some examples of what exactly should and should not match.
If you want to accept something like test_fool.pl
or test_bart.pl
, then you could change it to the following:
/test_(?!(foo|bar|baz)\.pl).*\.pl/
Upvotes: 6
Reputation: 15284
Hmm, I might have misunderstood your question. Anyway, maybe this is helpful ...
You would negate the match operator. For example:
perl -lwe "print for grep ! m/(lwp|archive).*\.pl/, glob q(*.pl)"
# Note you'd use single-quotes on Linux but double-quotes on Windows.
# Nothing to do with Perl, just different shells (bash vs cmd.exe).
The !
negates the match. The above is shorthand for:
perl -lwe "print for grep ! ($_ =~ m/(lwp|archive).*\.pl/), glob q(*.pl)"
Which can also be written using the negated match operator !~
, as follows:
perl -lwe "print for grep $_ !~ m/(lwp|archive).*\.pl/, glob q(*.pl)"
In case you're wondering, the glob
is simply used to get an input list of filenames as per your example. I just substituted another match pattern suitable for the files I had handy in a directory.
Upvotes: 0