Perl 传递命令行参数
Perl passing command line arguments
我有一个程序目前接受 2 个或 3 个命令行参数 find.pl [i] <perlRegexPattern> <listOfFiles>.
现在,如果我通过 find.pl proj1 Data
或 find.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::Std
和 File::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.
我有一个程序目前接受 2 个或 3 个命令行参数 find.pl [i] <perlRegexPattern> <listOfFiles>.
现在,如果我通过 find.pl proj1 Data
或 find.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::Std
和 File::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.