我的perl脚本中有以下代码:
my $directory; my @files; my $help; my $man; my $verbose; undef $directory; undef @files; undef $help; undef $man; undef $verbose; GetOptions( "dir=s" => \$directory, # optional variable with default value (false) "files=s" => \@files, # optional variable that allows comma-separated # list of file names as well as multiple # occurrenceces of this option. "help|?" => \$help, # optional variable with default value (false) "man" => \$man, # optional variable with default value (false) "verbose" => \$verbose # optional variable with default value (false) ); if (@files) { @files = split(/,/,join(',', @files)); }
处理互斥命令行参数的最佳方法是什么?在我的脚本中,我只希望用户只输入“--dir”或“--files”命令行参数,但不能同时输入两者。反正配置Getopt来执行此操作吗?
感谢。
答案 0 :(得分:4)
我不认为Getopt :: Long有一种方法可以做到这一点,但它很容易自己实现(我假设有一个使用函数返回一个字符串,告诉用户如何打电话给程序):
die usage() if defined $directory and @files;
答案 1 :(得分:3)
为什么不呢:
if ($directory && @files) {
die "dir and files options are mutually exclusive\n";
}
答案 2 :(得分:2)
您可以简单地检查两个变量中是否存在值。
if(@files && defined $directory) {
print STDERR "You must use either --dir or --files, but not both.\n";
exit 1;
}
或者,如果您想简单地忽略在第一个--dir或--files之后指定的任何选项,您可以将两者都指向一个函数。
#!/usr/bin/perl
use Getopt::Long;
my $directory;
my @files;
my $mode;
my $help;
my $man;
my $verbose;
GetOptions(
"dir=s" => \&entries, # optional variable with default value (false)
"files=s" => \&entries, # optional variable that allows comma-separated
# list of file names as well as multiple
# occurrences of this option.
"help|?" => \$help, # optional variable with default value (false)
"man" => \$man, # optional variable with default value (false)
"verbose" => \$verbose # optional variable with default value (false)
);
sub entries {
my($option, $value) = @_;
if(defined $mode && $mode ne $option) {
print STDERR "Ignoring \"--$option $value\" because --$mode already specified...\n";
}
else {
$mode = $option unless(defined $mode);
if($mode eq "dir") {
$directory = $value;
}
elsif($mode eq "files") {
push @files, split(/,/, $value);
}
}
return;
}
print "Working on directory $directory...\n" if($mode eq "dir");
print "Working on files:\n" . join("\n", @files) . "\n" if($mode eq "files");
答案 3 :(得分:0)
use strict;
use warnings;
use Getopt::Long;
my($directory,@files,$help,$man,$verbose);
GetOptions(
'dir=s' => sub {
my($sub_name,$str) = @_;
$directory = $str;
die "Specify only --dir or --files" if @files;
},
# optional variable that allows comma-separated
# list of file names as well as multiple
# occurrences of this option.
'files=s' => sub {
my($sub_name,$str) = @_;
my @s = split ',', $str;
push @files, @s;
die "Specify only --dir or --files" if $directory;
},
"help|?" => \$help,
"man" => \$man,
"verbose" => \$verbose,
);
use Pod::Usage;
pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;
=head1 NAME sample - Using Getopt::Long and Pod::Usage =head1 SYNOPSIS sample [options] [file ...] Options: -help brief help message -man full documentation =head1 OPTIONS =over 8 =item B Print a brief help message and exits. =item B Prints the manual page and exits. =back =head1 DESCRIPTION B will read the given input file(s) and do something useful with the contents thereof. =cut
答案 4 :(得分:0)
您可以使用Getopt::Long::Descriptive
执行此操作。它与Getopt::Long
略有不同,但如果您打印使用情况摘要,则可以通过为您完成所有操作来减少重复。
在这里,我添加了一个名为source
的隐藏选项,因此$opt->source
将包含值dir
或files
,具体取决于给出的选项,以及将为您强制执行one_of
约束。给出的值将在$opt->dir
或$opt->files
中,无论哪一个都给出。
my ( $opt, $usage ) = describe_options(
'%c %o',
[ "source" => hidden => {
'one_of' => [
[ "dir=s" => "Directory" ],
[ "files=s@" => "FilesComma-separated list of files" ],
]
} ],
[ "man" => "..." ], # optional variable with default value (false)
[ "verbose" => "Provide more output" ], # optional variable with default value (false)
[],
[ 'help|?' => "Print usage message and exit" ],
);
print( $usage->text ), exit if ( $opt->help );
if ($opt->files) {
@files = split(/,/,join(',', @{$opt->files}));
}
您脚本其余部分的主要区别在于,所有选项都包含在$opt
变量的方法中,而不是每个变量都包含与Getopt::Long
类似的变量。