Perl传递命令行参数

时间:2017-10-26 03:01:52

标签: perl parameter-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
}

2 个答案:

答案 0 :(得分:1)

你的问题是 - 在你的perl脚本到达它们之前,shell会扩展通配符

尝试添加:

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

你会看到什么被传递到你的程序中。

鉴于您正在使用通配符,它​​可能会匹配多个东西 - 如果它匹配,那么您的程序将接收其他参数。只有您的程序接受3.

答案 1 :(得分:1)

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

#!/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:
  $0 [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.