5

我的 perl 脚本中有以下代码:

我的$目录;
我的文件;
我的帮助;
我的男人;
我的 $verbose;

undef $目录;
undef @files;
undef $帮助;
undef $人;
undef $详细;

获取选项(
           "dir=s" => \$directory, # 具有默认值的可选变量 (false)
           "files=s" => \@files, # 允许逗号分隔的可选变量
                                # 文件名列表以及多个
                    # 此选项的出现次数。
           “帮助|?” => \$help, # 具有默认值的可选变量 (false)
           "man" => \$man, # 具有默认值的可选变量 (false)
           "verbose" => \$verbose # 带有默认值的可选变量 (false)
          );

    如果(@files){
    @files = split(/,/,join(',', @files));
    }

处理互斥命令行参数的最佳方法是什么?在我的脚本中,我只希望用户只输入“--dir”或“--files”命令行参数,但不能同时输入。无论如何配置Getopt来做到这一点?

谢谢。

4

5 回答 5

4

我不认为 Getopt::Long 有办法做到这一点,但它很容易自己实现(我假设有一个使用函数返回一个字符串,告诉用户如何调用程序):

die usage() if defined $directory and @files;
于 2009-05-20T16:21:09.853 回答
3

为什么不只是这样:

if ($directory && @files) {
  die "dir and files options are mutually exclusive\n";
}
于 2009-05-20T16:24:04.623 回答
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");
于 2009-05-20T16:37:34.143 回答
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 名称

示例 - 使用 Getopt::Long 和 Pod::Usage

=head1 概要

示例 [选项] [文件 ...]

 选项:
   -help 简短的帮助信息
   -man 完整文档

=head1 选项

=超过 8

=项目B

打印简短的帮助信息并退出。

=项目B

打印手册页并退出。

=返回

=head1 描述

B 将读取给定的输入文件并做一些事情
对其内容有用。

=切
于 2009-05-20T21:42:29.753 回答
0

您可以使用Getopt::Long::Descriptive. 它与 有点不同Getopt::Long,但如果您要打印使用摘要,它会为您完成所有这些工作,从而有助于减少重复。

在这里,我添加了一个名为 的隐藏选项source,因此$opt->source它将包含值dirfiles取决于给定的选项,它将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变量的方法,而不是每个选项都有自己的变量,如 with Getopt::Long

于 2016-09-08T18:16:43.087 回答