Reputation: 389
I have a list of filenames prefixes in an array @list1
and a list of full filenames in a second array @list2
. In the end I want to end up with a third array containing only full filenames that do not match the prefixes in @list1
. I've started with:
for my $match (@list1) {
@list3 = grep { !/$match/ } @list2;
}
but it doesn't do what I thought it would do. What options do i have to get the result I'm looking for.
Upvotes: 4
Views: 188
Reputation: 6204
Perhaps an alternation regex will help:
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;
Output:
myfile.txt
otherfile.txt
Upvotes: 5
Reputation: 2668
If you want to use a more list-expression-like way (as in your example), you could work with this:
#!/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;
Output:
quux
alice
bob
Note: I used first
here instead of the core-grep
because with long @forbidden
lists it could be more efficient since it stops after the first (and possibly only) match.
Upvotes: 1
Reputation: 5801
#!/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;
yields
cow
fruitcake
orangutan
crabcake
Edited as per raina77ow's suggestions.
Upvotes: 0