代码之家  ›  专栏  ›  技术社区  ›  Thomas Owens

从第n项迭代到数组末尾的Perlish方法是什么?

  •  6
  • Thomas Owens  · 技术社区  · 15 年前

    问题是我有n个命令行参数。总是会有至少2个,但是最大的数字是无限的。第一个参数指定操作模式,第二个参数指定要处理的文件。第3个到第n个是要对该文件执行的操作(可能不是,因为用户可能只想清理该文件,如果只传递2个参数,就可以完成此操作)。

    我正在研究Perl中可用于处理数组的方法,但我不确定从项目3到数组末尾的迭代“Perlish”方式是什么。

    我看到的一些选择:

    • 从数组的末尾弹出,直到找到一个不以“-”开头的元素(因为文件路径不以“-”开头),尽管我认为它可能会导致问题。
    • 移动数组两次以删除前两个元素。不管我剩下什么,只要它的大小至少是1,我就可以迭代。

    我喜欢第二个选项,但我不知道它是否是珍珠色的。既然我正在尝试学习Perl,我不妨学习用Perl做事情的正确方法。

    8 回复  |  直到 15 年前
        1
  •  17
  •   user80168    15 年前

    除了像Sinan写的那样使用getopt模块,我可能会使用:

    my ( $operation, $file, @things ) = @ARGV;
    

    然后你可以:

    for my $thing_to_do ( @things ) {
    ...
    }
    
        2
  •  12
  •   FMc TLP    15 年前

    imho,完成你所需要的工作的珍珠笔方式是使用 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;
    }
    
        3
  •  9
  •   Robert P    15 年前

    我愿意 高度地 推荐使用 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) {
        ...
    }
    

    这允许您有一个长的选项名,并自动将信息填充到变量中,并允许您对其进行测试。它甚至允许您稍后添加额外的命令,而无需对参数进行任何额外的解析,例如添加“version”或“help”选项:

    # 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 ,因为 获取选项 将为您处理所有设置。

        4
  •  7
  •   brian d foy    15 年前

    在Perl中做事情的最标准方法是通过CPAN。

    所以我的第一选择是 Getopt::Long . 还有一个关于开发的教程: Processing Command Line Options with Perl

        5
  •  6
  •   ysth    15 年前

    你可以使用 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 )

        6
  •  3
  •   Sinan Ünür    15 年前

    迪佩兹的回答是一个很好的方法。

    您的第二个选项也没有问题:

    my $op     = shift; # implicit shift from @ARGV
    my $file   = shift; 
    my @things = @ARGV;
    
    # iterate over @things;
    

    你也可以跳过复制 @ARGV 进入之内 @things 直接处理。但是,除非脚本非常短、非常简单,并且不太可能随着时间的推移变得更复杂,否则我将避免采用过多的捷径。

    无论你选择迪佩兹的方法还是这一个很大程度上是一个品味问题。

    决定哪个更好真的是一个哲学问题。问题的关键在于你是否应该修改像 @ ARGV .有人会说,只要是以一种高度可见的方式来做,这没什么大不了的。其他人会争论赞成离开 @ ARGV 未触及的

    由于速度或内存问题,不注意任何人对一个选项或另一个选项的争论。这个 @ ARGV 阵列被大多数外壳限制在一个非常小的尺寸,因此使用一种方法比另一种方法没有明显的优化。

    Getopt::Long 如前所述,也是一个很好的选择。

        7
  •  3
  •   draegtun    15 年前

    一定要看看 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项1--things项2--things项3


    这些驼鹿类型被检查… ./getopt --oper "not a number" 生产:

    Value "not a number" invalid for option oper (number expected)

    免费的话,你总能得到一份使用清单;-)

    usage: getopt.pl [long options...]
             --file         bit about file
             --oper         op doc stuff
             --things    
    

    /I3AZ/

        8
  •  0
  •   Michael Cramer    15 年前

    对于任何数组的更一般的情况:

    for(my $i=2; $i<@array; $i++) {
        print "$array[$i]\n";
    }
    

    它在数组中循环,从第三个元素(索引2)开始。显然,您指定的特定示例,depesz的答案是最直接和最好的。