Perl 传递命令行参数

Perl passing command line arguments

我有一个程序目前接受 2 个或 3 个命令行参数 find.pl [i] <perlRegexPattern> <listOfFiles>. 现在,如果我通过 find.pl proj1 Datafind.pl -i proj1 Data,该程序将通过我的 if 语句,但是我想要更改它,以便我的程序将接受类似 find.pl -i ".*proj1.*" DataA/* 的内容,当我尝试传递它时,我的程序无法通过第二个 if 语句。我不太明白如何将它们作为参数传递,然后在我的程序中使用它们。

#!/usr/bin/perl -w
if(@ARGV < 2){
    print "\n2) Usage: find.pl [-i] <perlRegexPattern> <listOfFiles>\n\n";
    exit;
}
if(@ARGV > 3){
    print "\n3) Usage: find.pl [i] <perlRegexPattern> <listOfFiles>\n\n";
    exit;
}
if(@ARGV == 3 && $ARGV[0] ne "-i"){
    die "\n4) Usage: find.pl [i] <perlRegexPattern> <listOfFiles>\n\n";
}

if ($#ARGV eq 1 ){
    print "normal case\n";
    my ($pattern, $filelist) = @ARGV;
    print "$pattern $filelist\n";
    opendir( DIR , $filelist ) or die "\nCannot open directory $filelist\n\n";

    while ( ($fp = readdir(DIR)) ){
        if( $fp =~ m/$pattern/){
            print "$fp\n";
        }
        elsif( $fp =~ m/.*\.txt/){
            print "$fp is a text file\n";   #Still working on this part
            open( FILE, '<' , $fp) or die ("\nCould not open file $fp\n\n");
            while( <FILE> ){
                if($_ =~ m/$pattern/){
                    print "$fp : $_ : line pattern match\n";
                    last;
                }
            }
            close(FILE);
        }
    }
}
else{
    print "-i case\n";
    my ($pattern, $filelist) = @ARGV[1 .. 2];
    print "$pattern $filelist\n";
    #TODO
}

您的问题是 - shell 在您的 perl 脚本到达它们之前 扩展了通配符。

尝试添加:

use Data::Dumper;
print Dumper \@ARGV;

您将看到传递到您的程序中的内容。

鉴于您使用的是通配符,它​​很可能会匹配不止一件事 - 如果匹配,那么您的程序将收到额外的参数。只有您的程序 接受 3。

查看标准模块 Getopt::StdFile::Find,注意您可以使用 local@ARGV 保存一些 open/close 语句:

#!/usr/bin/perl -w

use strict;
use Getopt::Std;
use File::Find;

##  Parse option(s)
getopts 'i', \my %opt;

##  Show help
die <<usage unless @ARGV > 1;
Usage:
  [=10=] [options] pattern searchpaths...

Options:
  -i    Case insensitive search
usage

##  Compile regex
my $re = shift;
if ($opt{i}) { $re = qr($re)i }
else         { $re = qr($re) }

##  Walk searchpaths
find (sub
  {
    ##  Filename matches the regex
    if (/$re/)
    {
      printf "match name:    %s\n", $File::Find::name
    }
    ##  File is regular, name ends with .txt, and...
    elsif (-f and /\.txt$/)
    {
      local @ARGV = $_;
      while (<>)
      {
        ##  ... a line in the file matches the regex.
        chomp;
        /$re/ 
          and printf "match content: %s: %s\n", $File::Find::name, $_
          and last;
      }
    }
  },
  @ARGV);

示例:

find.pl -i ^fa /usr/share/doc/lighttpd

输出:

match name:    /usr/share/doc/lighttpd/fastcgi-state.txt
match name:    /usr/share/doc/lighttpd/fastcgi.txt
match content: /usr/share/doc/lighttpd/security.txt: FastCGI
match content: /usr/share/doc/lighttpd/accesslog.txt: fastcgi + chroot
match content: /usr/share/doc/lighttpd/performance.txt: failed'. This is very rare and might only occur in test setups.