Perl:使用 GetOpt 时是否可以防止选项识别在双破折号(--)后停止?

发布于 2024-10-17 06:56:46 字数 235 浏览 6 评论 0原文

我希望在 Perl 脚本中写下接收和选项,其值列表以双破折号 (--) 结尾。 示例:

% perl_script -letters a b c -- -words he she we --

运行此命令行的结果是,将创建两个数组: 字母= [abc ]; 单词= [他她我们];

使用 GetOption 不支持这一点,因为使用 double dash 后,选项识别停止。

I wish to write down in perl scripts that receive and option with values lists that ends with double dash (--).
example:

% perl_script -letters a b c -- -words he she we --

as result of running this command line, two arrays will be created:
letters = [a b c ];
words = [he she we];

Using GetOption does not support this, b.c after using double dash , the options recognitions stops.

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

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

发布评论

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

评论(4

放我走吧 2024-10-24 06:56:46

您有什么具体原因使用如此令人困惑的分隔符吗? -- 对于大多数脚本用户来说都有已知的含义,但事实并非如此。

如果您需要读取带有列表的选项,Getopt::Long 有处理输入数组的方法,也许这样的东西可以帮助你;查看“具有多个值的选项”。该模块位于标准发行版中,因此您甚至无需安装任何东西。我将它用于任何需要多个(可能是两个)输入的脚本,并且肯定是否有任何输入是可选的。

另请参阅此处以及更多此处

这是一个简单的例子,如果您可以灵活地更改输入语法,这将获得您所请求的功能:

#!/usr/bin/env perl
# file: test.pl

use strict;
use warnings;

use Getopt::Long;

my @letters;
my @words;

GetOptions(
  "letters=s{,}" => \@letters,
  "words=s{,}" => \@words
);

print "Letters: " . join(", ", @letters) . "\n";
print "Words: " . join(", ", @words) . "\n";

给出:

$ ./test.pl --letters a b c --words he she we
Letters: a, b, c
Words: he, she, we

虽然我永远不会鼓励编写自己的解析器,但我无法理解为什么有人会选择您所拥有的形式,所以我将假设您无法控制这种格式并且需要解决它。如果是这种情况(否则,请考虑更标准的语法并使用上面的示例),这里有一个简单的解析器可以帮助您入门。

注意,不要自己编写的原因是其他的已经经过充分测试并且已经解决了边缘案例。您还知道如何处理 ---title 之间的内容吗?我假设,由于新的标题将结束前一个标题,因此您可能会在两者之间有一些东西,并将所有这些按顺序集中在“默认”键中。

#!/usr/bin/env perl
# file: test_as_asked.pl
# @ARGV = qw/default1 -letters a b c -- default2 -words he she we -- default3/;

use strict;
use warnings;

my %opts;
# catch options before a -title (into group called default)
my $current_group = 'default';
foreach my $opt (@ARGV) {
  if ($opt =~ /\-\-/) {
    # catch options between a -- and next -title
    $current_group = 'default';
  } elsif ($opt =~ /\-(.*)/) {
    $current_group = $1;
  } else {
    push @{ $opts{$current_group} }, $opt;
  }
}

foreach my $key (keys %opts) {
  print "$key => " . join(", ", @{ $opts{$key} }) . "\n";
}

给出:

$ ./test_as_asked.pl default1 -letters a b c -- default2 -words he she we -- default3
letters => a, b, c
default => default1, default2, default3
words => he, she, we

Do you have some specific reason to use such a confusing delimiter? -- has a known meaning to most script users and this is not it.

If you need to read in options with lists, Getopt::Long has methods to deal with input arrays, perhaps something like this could help you; look under "Options with multiple values". This module is in the standard distribution, so you don't even have to install anything. I use it for any script that needs more than one (maybe two) inputs and definitely if any inputs are optional.

See also here and even more here.

Here is a quick example, if you have the flexibility to change your input syntax, this gets you the functionality you are requesting:

#!/usr/bin/env perl
# file: test.pl

use strict;
use warnings;

use Getopt::Long;

my @letters;
my @words;

GetOptions(
  "letters=s{,}" => \@letters,
  "words=s{,}" => \@words
);

print "Letters: " . join(", ", @letters) . "\n";
print "Words: " . join(", ", @words) . "\n";

Gives:

$ ./test.pl --letters a b c --words he she we
Letters: a, b, c
Words: he, she, we

While I would never encourage writing one's own parser, I could not understand why someone would choose the form you had, so I am going to operate under the assumption that you are not in control of this format and need to work around it. If this is the case (otherwise, please consider a more standard syntax and use the example above), here is a simple parser that should get you started.

N.B. the reason NOT to write your own is others are well tested and have fringe cases ironed out. Also do you know what you would do with something between a -- and a -title? I assumed that since a new -title would end the previous one, that you might have something between and have lumped all these in order in a 'default' key.

#!/usr/bin/env perl
# file: test_as_asked.pl
# @ARGV = qw/default1 -letters a b c -- default2 -words he she we -- default3/;

use strict;
use warnings;

my %opts;
# catch options before a -title (into group called default)
my $current_group = 'default';
foreach my $opt (@ARGV) {
  if ($opt =~ /\-\-/) {
    # catch options between a -- and next -title
    $current_group = 'default';
  } elsif ($opt =~ /\-(.*)/) {
    $current_group = $1;
  } else {
    push @{ $opts{$current_group} }, $opt;
  }
}

foreach my $key (keys %opts) {
  print "$key => " . join(", ", @{ $opts{$key} }) . "\n";
}

Gives:

$ ./test_as_asked.pl default1 -letters a b c -- default2 -words he she we -- default3
letters => a, b, c
default => default1, default2, default3
words => he, she, we
荒岛晴空 2024-10-24 06:56:46

怎么样

-letters "a b c" -words "he she we" 

How about

-letters "a b c" -words "he she we" 

?

我还不会笑 2024-10-24 06:56:46

如果需要,您可以多次处理您的论点。查看 pass_through 选项。这就是我在 ack 中所做的,因为某些选项会影响其他选项,所以我必须首先处理 --type 选项,并且然后处理剩下的事情。

You can handle your arguments in multiple passes if you want. Look at the pass_through option. This is what I do in ack because some options affect other options, so I have to handle the --type options first, and then handle out the rest.

那支青花 2024-10-24 06:56:46

禁用 dash dash 后门是不好的做法。

It's bad practice to disable the dash dash backdoor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文