是否有CPAN方法来解析随机命令行选项?

时间:2012-11-28 20:18:27

标签: perl command-line-arguments

使用Perl处理任意命令行选项是否有良好(理想的CPAN)方式?

例如,取一个字符串"-a 1 -b 'z -x' -c -d 3 4"并生成一个类似GetOpt::Long的数据结构:

 { a=>1, b=>"z -x", c=>1, d=>[3,4] }  # d=>"3 4" is acceptable

需要注意的是

  1. 预先不知道这组选项;所以我们似乎无法按原样使用GetOpt::Long

  2. 值本身可以包含其他选项,因此简单地解析#\b+-(\S+)\b#模式的字符串以查找THAT字符串中的所有选项似乎也是不可能的,并且一些参数的变得更复杂= s类型,some = s @,某些“-xabc”类型。

  3. 此外,即使我们可以做#2,GetOptionsFromString是否也支持正确的引用值的引用值?


  4. 注意:假设练习的目的是所有参数都是“选项”,换句话说,如果你将字符串拆分成(可能是引用的)标记,你的结构总是

     "-opt1 arg1a [arg1b] -opt2 ....".
    

    换句话说,任何以短划线开头的单词/标记都是一个新选项,所有不以短划线开头的后续单词/标记都是该选项的值。

2 个答案:

答案 0 :(得分:4)

使用Text :: Parsewords和简单状态机的快速示例。

#!/usr/bin/env perl

use strict;
use warnings;

use Text::ParseWords qw/shellwords/;

my $str = q{-a 1 -b 'z -x' -c -d 3 4};
my $data = parse($str);

use Data::Printer;
p $data;

sub parse {
  my $str = shift;

  my @tokens = shellwords $str;

  my %data;
  my @keys;
  my $key = '_unknown';
  foreach my $token (@tokens) {
    if ($token =~ s/^\-//) {
      $key = $token;
      push @keys, $key;
      next;
    }

    if ( ref $data{$key} ) {
      push @{ $data{$key} }, $token;
    } elsif (defined $data{$key}) {
      $data{$key} = [ $data{$key}, $token ];
    } else {
      $data{$key} = $token;
    }
  }

  foreach my $key (@keys) {
    next if defined $data{$key};
    $data{$key} = 1;
  }

  return \%data;
}

答案 1 :(得分:1)

在我了解Getopt::Long以及使用它的智慧之前,我推出了自己的命令行选项处理器,它将采用任意参数并填充全局哈希表。规则是

用单个字母切换(-A .. -Z,-a .. -z)

-n               sets  $args{"n"} = 1
-nfoo            sets  $args{"n"} = "foo"

切换多个字母

--foo            sets  $args{"foo"} = 1
--foo=bar        sets  $args{"foo"} = "bar"

这种方法的喜悦和伤害是您可以快速尝试新的命令行选项,在使用该选项时更改代码而无需编辑对GetOptions的调用或必须分配另一个变量:

 ... line 980 ...
 if ($args{"do-experimental-thing"}) {
     # new code
     do_experimental_thing();
 } else {
     do_normal_thing();
 }

这是我上传到CPAN的第一个模块,我已将其删除,但BackPAN内存很长。