从第 n 项迭代到数组末尾的 Perlish 方法是啥?
Posted
技术标签:
【中文标题】从第 n 项迭代到数组末尾的 Perlish 方法是啥?【英文标题】:What is the Perlish way to iterate from item n to the end of an array?从第 n 项迭代到数组末尾的 Perlish 方法是什么? 【发布时间】:2010-12-04 00:03:18 【问题描述】:问题是我有 n 个命令行参数。总是至少有 2 个,但最大数量是无限的。第一个参数指定操作模式,第二个参数是要处理的文件。第 3 到第 n 是对文件执行的操作(可能没有,因为用户可能只想清理文件,如果您只传递 2 个参数就可以完成)。
我正在查看 Perl 中可用于处理数组的方法,但我不确定从第 3 项迭代到数组末尾的“Perlish”方式是什么。
我见过的一些选项:
从数组末尾弹出,直到我找到一个不以“-”开头的元素(因为文件路径不以“-”开头,尽管我认为它可以,这可能会导致问题)。 移动数组两次以删除前两个元素。无论我剩下什么,我都可以迭代,只要它的大小至少为 1。我喜欢第二种选择,但我不知道它是不是 Perlish。既然我正在努力学习 Perl,我不妨学习一下在 Perl 中做事的正确方法。
【问题讨论】:
【参考方案1】:对于任何数组的更一般情况:
for(my $i=2; $i<@array; $i++)
print "$array[$i]\n";
循环遍历数组,从第三个元素(索引 2)开始。显然,您指定的具体示例,depesz 的答案是最直接和最好的。
【讨论】:
【参考方案2】:在 Perl 中最标准的处理方式是通过 CPAN。
所以我的第一选择是Getopt::Long。 DevShed上也有教程:Processing Command Line Options with Perl
【讨论】:
Getopt::Long 一直是核心模块(尽管 CPAN 上随时可能有更新的版本)。【参考方案3】:请查看MooseX::Getopt,因为它可能会激起您对更多事物的兴趣Moosey!。
MooseX::Getopt 示例:
# getopt.pl
package MyOptions;
use Moose;
with 'MooseX::Getopt';
has oper => ( is => 'rw', isa => 'Int', documentation => 'op doc stuff' );
has file => ( is => 'rw', isa => 'Str', documentation => 'about file' );
has things => ( is => 'rw', isa => 'ArrayRef', default => sub [] );
no Moose;
my $app = MyOptions->new_with_options;
for my $thing (@ $app->things )
print $app->file, " : ", $thing, "\n";
# => file.txt : item1
# => file.txt : item2
# => file.txt : item3
这样运行时会产生上述情况:
perl getopt.pl --oper 1 --file file.txt --things item1 --things item2 --things item3
检查这些 Moose 类型..../getopt --oper "not a number"
产生:
值“不是数字”对选项操作无效(预期数字)
而且您总是可以免费获得使用清单 ;-)
用法:getopt.pl [长选项...] --file 关于文件的位 --oper op 文档的东西 - 事物/I3az/
【讨论】:
为什么当 Moose 超出范围时,你no Moose;
正确?还是 Moose 没有作用域?
Moose 是作用域的,但它确实将“has”、“with”和其他糖导入“MyOptions”命名空间。 “没有驼鹿;”删除这个糖,这样你就不会无意中做类似 $app->has ;-)【参考方案4】:
我会强烈推荐使用Getopt::Long 来解析命令行参数。这是一个标准模块,它工作得非常棒,并且让你想要做的事情变得轻而易举。
use strict;
use warnings;
use Getopt::Long;
my $first_option = undef;
my $second_option = undef;
GetOptions ('first-option=s' => \$first_option,
'second-option=s' => \$second_option);
die "Didn't pass in first-option, must be xxxyyyzzz."
if ! defined $first_option;
die "Didn't pass in second-option, must be aaabbbccc."
if ! defined $second_option;
foreach my $arg (@ARGV)
...
这让您有一个长选项名称,并自动为您将信息填充到变量中,并允许您对其进行测试。它甚至可以让您稍后添加额外的命令,而无需对参数进行任何额外的解析,例如添加“版本”或“帮助”选项:
# adding these to the above example...
my $VERSION = '1.000';
sub print_help ...
# ...and replacing the previous GetOptions with this...
GetOptions ('first-option=s' => \$first_option,
'second-option=s' => \$second_option)
'version' => sub print "Running version $VERSION"; exit 1 ,
'help' => sub print_help(); exit 2 );
然后,您可以使用-
、--
、第一个字母或整个选项在命令行上调用它,GetOptions
会为您计算出一切。它使你的程序更健壮,更容易理解;你可以说它更“可猜测”。最好的部分是您永远不必更改处理@ARGV
的代码,因为GetOptions
将为您处理所有设置。
【讨论】:
【参考方案5】:deepesz 答案是一种很好的方法。
你的第二个选项也没有错:
my $op = shift; # implicit shift from @ARGV
my $file = shift;
my @things = @ARGV;
# iterate over @things;
您也可以跳过将@ARGV
复制到@things
并直接处理它。但是,除非脚本非常短、非常简单,并且随着时间的推移不太可能变得更加复杂,否则我会避免走太多捷径。
您是选择 deepesz 的方法还是这个方法在很大程度上取决于口味。
决定哪个更好实际上是一个哲学问题。问题的症结在于你是否应该修改像@ARGV
这样的全局变量。有人会说,只要以高度可见的方式完成,这没什么大不了的。其他人会主张让@ARGV
保持不变。
不要注意任何人因为速度或内存问题而争论支持一种或另一种选择。 @ARGV
数组被大多数 shell 限制为非常小的大小,因此使用一种方法比另一种方法没有显着的优化。
Getopt::Long,如前所述,也是一个很好的选择。
【讨论】:
【参考方案6】:您可以使用slice 提取第二个。到最后一项,例如:
[dsm@localhost:~]$ perl -le 'print join ", ", @ARGV[2..$#ARGV];' 1 2 3 4 5 6 7 8 9 10 00
3, 4, 5, 6, 7, 8, 9, 10, 00
[dsm@localhost:~]$
但是,您可能应该使用shift
(或者更好的是GetOpt::Long
)
【讨论】:
【参考方案7】:恕我直言,完成您需要的 Perlish 方法是使用 Getopt modules on CPAN 之一。
如果你还想手工做,我会选择第二个选项(这类似于我们处理方法调用的第一个参数的方式):
die "Must provide filename and operation\n" unless @ARGV >= 2;
my $op = shift @ARGV;
my $file = shift @ARGV;
if ( @ARGV )
# handle the other arguments;
【讨论】:
【参考方案8】:除了像 Sinan 写的那样使用 Getopt 模块,我可能会选择:
my ( $operation, $file, @things ) = @ARGV;
然后你可以:
for my $thing_to_do ( @things )
...
【讨论】:
虽然这在技术上是一种解决方案,但 Getopt::Long 是一个标准的 perl 模块,它提供了一种快速、干净和健壮的方式来处理命令行参数。我强烈建议您查看它(以及我的示例,如下所示)。 要做这样微不足道的事情,我认为使用另一个模块可能有点矫枉过正。这似乎可以满足我的需要。 好的,如果这就是你想要的。然而,对于其他任何人来说,当涉及到 Getopt::Long 这样的核心模块时,几乎没有理由犹豫使用它们——模块重用几乎是你所能得到的。多年来,核心模块都经过了彻底的测试、优化和审查,可以使@ARGV 解析等常见任务尽可能简单和无问题。以上是关于从第 n 项迭代到数组末尾的 Perlish 方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章