Perl Getopt::长相关问题 - 互斥的命令行参数

发布于 2024-07-22 14:44:35 字数 993 浏览 10 评论 0原文

我的 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));
    }

What is the best way to processmutual Exclusive Command Line Arguments? 在我的脚本中,我只希望用户仅输入“--dir”或“--files”命令行参数,但不能同时输入两者。 是否有配置 Getopt 来执行此操作?

谢谢。

I have the following code in my perl script:


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));
    }

What is the best way to handle mutually exclusive command line arguments? In my script I only want the user to enter only the "--dir" or "--files" command line argument but not both. Is there anyway to configure Getopt to do this?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦醒灬来后我 2024-07-29 14:44:35

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

die usage() if defined $directory and @files;

I don't think there is a way in Getopt::Long to do that, but it is easy enough to implement on your own (I am assuming there is a usage function that returns a string that tells the user how to call the program):

die usage() if defined $directory and @files;
空‖城人不在 2024-07-29 14:44:35

为什么不只是这个:

if ($directory && @files) {
  die "dir and files options are mutually exclusive\n";
}

Why not just this:

if ($directory && @files) {
  die "dir and files options are mutually exclusive\n";
}
不知在何时 2024-07-29 14:44:35

您可以简单地检查两个变量中是否存在值。

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");

You can simply check for the existence of values in both variables.

if(@files && defined $directory) {
    print STDERR "You must use either --dir or --files, but not both.\n";
    exit 1;
}

Or, if you would like to simply ignore any options specified after the first --dir or --files, you can point both at a function.

#!/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");
轻拂→两袖风尘 2024-07-29 14:44:35

您可以使用 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 变量的方法包含,而不是像 Getopt::Long 那样每个选项都有自己的变量代码>.

You can do this with Getopt::Long::Descriptive. It's a bit different from Getopt::Long, but if you're printing a usage summary, it helps to reduce duplication by doing all that for you.

Here, I've added a hidden option called source, so $opt->source which will contain the value dir or files depending on which option was given, and it will enforce the one_of constraint for you. The values given will be in $opt->dir or $opt->files, whichever one was given.

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}));
}

The main difference for the rest of your script is that all the options are contained as methods of the $opt variable, rather than each one having its own variable like with Getopt::Long.

徒留西风 2024-07-29 14:44:35
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文