문제

I would like to find out if a file has a particular file extension, selected in a list of extensions.

I had this initial idea:

my $file = "filename.zip";
my @allowedExts = ( '.zip', '.tar.gz', '.tar.bz2' );

my $found = 0;
foreach $ext (@allowedExts) {
  if (index($file, $ext) != -1) {
    $found = 1;
    last;
  }
}

print "found" if ($found);

Is there a simpler way to do that?

도움이 되었습니까?

해결책 2

index is not a good idea here, you might get very unexpected behaviour if the extension itself is found somewhere in the middle of filename.

Also: ALWAYS use strict and use warnings

Regex matching at the end of the string will be a better solution here, see the code below. $ is a metacharacter used to match the end of the line (or before newline at the end)

#!/usr/bin/perl                                                                                                                                                                                                                                              
use strict;
use warnings;

my $file = "filename.zip";
my @allowedExts = ( '.zip', '.tar.gz', '.tar.bz2' );

my $found = 0;
foreach my $ext (@allowedExts) {
    if ($file =~ /\Q$ext\E$/) {
        $found = 1;
        last;
    }
}

print "found" if ($found);

You will probably get loads of other ideas for solving this. As always with perl: TIMTOWTDI.

EDIT: As @ikegami suggested, regex should be escaped so that the dot is not treated as metacharacter but literal match, \Q and \E escape metacharacters in the regex.

다른 팁

If you truly have many extensions (not just three), avoid the loop by finding the extension first, then checking a hash:

my $file = "filename.zip";
my @allowedExts = ( '.zip', '.tar.gz', '.tar.bz2' );

my %allowedExts;
@allowedExts{@allowedExts} = ();
my (undef, $ext) = split /(?=\.)/, $file, 2;

my $found = $ext && exists $allowedExts{$ext};

The above will treat everything in the filename starting from the first .; if you have . in the filename before what you want to find as an extension, you can assemble all the extensions into a single regex:

my $file = "filename.zip";
my @allowedExts = ( '.zip', '.tar.gz', '.tar.bz2' );

my $found = $filename =~ ( join( '|', map quotemeta, @allowedExts ) . '\z' );
use List::Util qw(first);

my $file = "filename.zip";
my @allowedExts = map qr/\Q$_$/, ( '.zip', '.tar.gz', '.tar.bz2' );

my $found = first { $file =~ /$_/ } @allowedExts;

Anther approach is to use regular expressions.

Build the regex:

my @allowedExts = qw( .zip .tar.gz .tar.bz2 );
my $pat = join '|', map quotemeta, @allowedExts;
my $re  = qr/$pat\z/;

Use it:

my $file = "filename.zip";
print "Found\n" if $file =~ $re;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top