我有一个数组中的文件名前缀@list1
列表和第二个数组中的完整文件名列表@list2
。最后,我想得到第三个数组,其中仅包含与 . 中的前缀不匹配的完整文件名@list1
。我开始了:
for my $match (@list1) {
@list3 = grep { !/$match/ } @list2;
}
但它没有做我认为它会做的事情。我有什么选择才能得到我正在寻找的结果。
我有一个数组中的文件名前缀@list1
列表和第二个数组中的完整文件名列表@list2
。最后,我想得到第三个数组,其中仅包含与 . 中的前缀不匹配的完整文件名@list1
。我开始了:
for my $match (@list1) {
@list3 = grep { !/$match/ } @list2;
}
但它没有做我认为它会做的事情。我有什么选择才能得到我正在寻找的结果。
也许交替正则表达式会有所帮助:
use strict;
use warnings;
my @list1 = qw/a.f c data g j/;
my @list2 = qw/myfile.txt a.file.txt data.txt otherfile.txt jargon.txt/;
my $regex = join '|', map "\Q$_\E", @list1;
my @list3 = grep !/^(?:$regex)/, @list2;
print "$_\n" for @list3;
输出:
myfile.txt
otherfile.txt
如果您想使用更像列表表达式的方式(如您的示例中所示),您可以使用以下方法:
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util 'first';
use feature 'say';
my @filenames = qw(foo bar baz quux alice bob);
my @forbidden = qw(f ba);
my @matching = grep {
my $filename = $_;
not defined first { $filename =~ /^\Q$_/ } @forbidden;
} @filenames;
say for @matching;
输出:
quux
alice
bob
注意:我first
在这里使用了 core- 而不是 core- grep
,因为对于长@forbidden
列表,它可能会更有效,因为它在第一个(并且可能只有一个)匹配后停止。
#!/usr/bin/perl
use strict;
use warnings;
my @prefixes = qw(a b d);
my @items = qw(apple banana cow dog fruitcake orangutan crabcake deer);
my @nonmatching;
ITEMS: foreach my $item (@items) {
foreach my $prefix (@prefixes) {
next ITEMS if ($item =~ /^$prefix/)
}
push @nonmatching, $item
}
$,=$\="\n";
print @nonmatching;
产量
cow
fruitcake
orangutan
crabcake
根据raina77ow 的建议进行编辑。