Reputation: 12747
I have an array of file names that I want to detect using perl.
I have a lot more than these, but this example is just to illustrate:
@toremove = (100, 102, 104, 131, 156);
Now I want to open the directory and go through the files and if they happen to have any of the filenames as in the array above, I want to take some action.
opendir (DIR, "D:/MYPATH/");
while (my $file = readdir(DIR)) {
if($file =~ <how do i reference an array item here?>.txt)
{ // do something }
Is there any way to say if the file happens to match any of the items in the array? So this is more like a "variable string match"...
Upvotes: 1
Views: 96
Reputation: 525
Here is a couple of alternatives:
## Shorthand hash definition
@toremove{100, 102, 104, 131, 156}= (1) x 5;
## Using a glob instead of opendir
for (<D:/MYPATH/*>)
{
## Use a regex for flexibility
if (m:.*/(.+)$: and $toremove{$1})
{
print "Doing something to $_\n";
}
}
Upvotes: 0
Reputation: 107080
Whenever you say to yourself How can I quickly find something in a list, you should say to yourself Hash!.
Let's take that @toremove
list, and turn it into a hash. We can do this with the map command. The map command is a bit scary at first, and I don't believe the manpage for it does it justice. It isn't really that complex:
@some_hash_or_array = map { .... } @original_array;
map takes @original_array
and loops through each entry of that array. The {...}
is a small program you want to run on each entry.
You can think of map as something like this:
my @original_array = qw( ... );
my @some_hash_or_array;
for my $entry ( @original_array ) {
push @some_hash_or_array, { ... };
}
What makes map useful is that each entry of the array is set to $_
, so manipulating $_
allows you to transform your array.
What I am doing is:
my %files = map { $_.".txt" => 1 } @to_remove;
When this map command processes @to_remove
, it creates another array that looks like this:
("100.txt" => 1, "102.txt" => 1, "104.txt" => 1, "131.txt" => 1, "156.txt" => 1)
I initialize my %files
hash with this array. Odd entries are the keys to the hash and the even entries following the keys are the data.
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables)
use feature qw(say);
my @to_remove = qw(100 102 104 131 156);
my %files = map { $_.".txt" => 1 } @to_remove;
while ( my $file = <DATA> ) {
chomp $file;
if ( exists $files{$file} ) {
say qq(File "$file" is in the list);
}
else {
say qq(File "$file" isn't in the list);
}
}
__DATA__
100.txt
203.txt
130.txt
104.txt
150.txt
156.txt
160.txt
This produces:
File "100.txt" is in the list
File "203.txt" isn't in the list
File "130.txt" isn't in the list
File "104.txt" is in the list
File "150.txt" isn't in the list
File "156.txt" is in the list
File "160.txt" isn't in the list
You'll need to do this:
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use autodie; # Automatically kills the program if opens fail
use feature qw(say);
my @to_remove = qw(100 102 104 131 156);
opendir my $dir_fh, "dir_name";
my %files = map { $_.".txt" => 1 } @to_remove;
while ( my $file = < $dir_fh > ) {
if ( exists $files{$file} ) {
say qq(File "$file" is in the list);
}
else {
say qq(File "$file" isn't in the list);
}
}
Upvotes: 2
Reputation: 2053
I'd transform the array to hash first and then simply test if the key exists in the hash.
my @toremove = (100, 102, 104, 131, 156);
my %lookup_hash;
$lookup_hash{"$_.txt"} = 1 for @toremove;
opendir (my $DIR, "D:/MYPATH/");
while (my $file = readdir($DIR)) {
if( $lookup_hash{$file} )
{ // do something }
Upvotes: 2
Reputation: 91488
I'd transform each element of the array then use the smart-match operator:
#!/usr/bin/perl
use Modern::Perl;
my @toremove = (100, 102, 104, 131, 156);
my @txt = map{$_.'.txt'}@toremove;
while(<DATA>) {
chomp;
if ($_ ~~ @txt) {
say "==> $_ : found";
} else {
say "$_ : NOT found";
}
}
__DATA__
abc
def.txt
100
102.txt
131.abc
156.txt
Output:
abc : NOT found
def.txt : NOT found
100 : NOT found
==> 102.txt : found
131.abc : NOT found
==> 156.txt : found
Upvotes: 1