2010-11-12 75 views
1

對於我正在編寫的perl腳本,可能會提供很多(〜50)的命令行選項。他們中的大多數是可選的,所以通話只會提供一些選項。如何在Perl中使用Getopt時對參數進行分組?

我正在使用Getopt::Long,但它不允許我多次使用GetOptions。因此,我必須在一個GetOptions調用中使用所有的命令行選項。

在使用GetOptions時是否有一些很好的方法將選項分組?

$ cat test.pl 
use strict; 
use warnings; 
use Getopt::Long; 

my ($a, $b, $c, $d); 

GetOptions ('a=s' => \$a, 'b=s' => \$b); 
GetOptions ('c=s' => \$c, 'd=s' => \$d); 

print "a = $a\nb = $b\nc = $c\nd = $d\n"; 

$ perl test.pl -a=AA -b=BB -c=CC -d=DD 
Unknown option: c 
Unknown option: d 
Use of uninitialized value in concatenation (.) or string at test.pl line 10. 
Use of uninitialized value in concatenation (.) or string at test.pl line 10. 
a = AA 
b = BB 
c = 
d = 
$ 

回答

1

出了什麼問題:

GetOptions(
    'a=s' => \$a, 
    'b=s' => \$b, 
    'c=s' => \$c, 
    'd=s' => \$d, 
); 

或者,如果他們都短,你可以這樣做:

GetOptions(
    'a=s' => \$a, 'b=s' => \$b, 
    'c=s' => \$c, 'd=s' => \$d, 
); 

(請注意,這是一個壞主意,用$a$bsort以外的任何東西)。

+0

正如我在問題中提到的,我有大約50個,如果他們沒有分組,很難跟蹤他們。 – Lazer 2010-11-12 10:19:18

+1

@Lazer,那麼你將不得不更好地解釋「分組」的含義。 GetOptions不關心他們列出的順序;以任何對你有意義的順序列出它們。 – cjm 2010-11-12 10:27:14

6

這可能是一個好主意來存儲你的選擇在一個散而不是:

Getopt::Long : Storing options values in a hash


有時候,例如當有 很多選擇,有一個單獨的 變量它們每個都可以是 繁瑣。 GetOptions()支持,作爲 一個替代機制,存儲 選項值在一個散列。

要獲取此信息,必須將對散列 的引用作爲第一個參數 傳遞給GetOptions()。對於在命令行上指定的每個選項 , 選項值將存儲在 哈希中,並且選項名稱爲關鍵字。實際上未上 命令行中使用 選項將不會在 放散列,上換句話說, exists($h{option})(或defined())可以 被用來測試是否使用一個選項。 的缺點是,如果該計劃下的使用 嚴格的運行,並使用$h{option}沒有 測試與exists()defined() 第一警告將被 發行。

my %h =(); 
GetOptions (\%h, 'length=i');  # will store in $h{length} 

對於採用列表或哈希值的選項,它是 必要 爲表示該情況 類型後附加一個@或%符號:

GetOptions (\%h, '[email protected]');  # will push to @{$h{colours}} 

爲了讓事情變得更復雜,散列可以 包含實際 目的地的引用,例如:

my $len = 0; 
my %h = ('length' => \$len); 
GetOptions (\%h, 'length=i');  # will store in $len 

本示例完全等同於:

my $len = 0; 
GetOptions ('length=i' => \$len); # will store in $len 

任何混合都是可能的。例如,最 常用的選項可以存儲在變量 ,而所有其他 選項獲取存儲在哈希:

my $verbose = 0;     # frequently referred 
my $debug = 0;      # frequently referred 
my %h = ('verbose' => \$verbose, 'debug' => \$debug); 
GetOptions (\%h, 'verbose', 'debug', 'filter', 'size=i'); 
if ($verbose) { ... } 
if (exists $h{filter}) { ... option 'filter' was specified ... } 
+1

+1 - 除了其他原因,一旦你開始做任何複雜的開發,有單個變量的選項而不是散列,你可以作爲一個整體傳遞給對象的構造函數是非常痛苦的。 – DVK 2010-11-12 17:03:23

0

通常陣列夷爲平地到一個列表被傳遞給函數之前,儘管一些函數覆蓋了這種行爲。使用這個,您可以定義選項組的數組,並將數組列表傳遞給GetOptions。

use strict; 
use warnings; 
use Getopt::Long; 

my ($opt_a, $opt_b, $opt_c, $opt_d); 

my @opt_group_1 = ('a=s' => \$opt_a, 'b=s' => \$opt_b); 
my @opt_group_2 = ('c=s' => \$opt_c, 'd=s' => \$opt_d); 
GetOptions(@opt_group_1, @opt_group_2); 

print "a = $opt_a\nb = $opt_b\nc = $opt_c\nd = $opt_d\n"; 

您可以將它與存儲值結合在一個散列中,以防止在Zaid提到時創建大量的選項變量。

use strict; 
use warnings; 
use Getopt::Long; 

my @opt_group_1 = ('a=s', 'b=s'); 
my @opt_group_2 = ('c=s', 'd=s'); 

my %opt; 

GetOptions(\%opt, @opt_group_1, @opt_group_2); 

print "a = $opt{a}\nb = $opt{b}\nc = $opt{c}\nd = $opt{d}\n"; 
2

最直接的答案是使用的Getopt ::龍::配置,像這樣:

use strict; 
use warnings; 
use Getopt::Long; 

my ($a, $b, $c, $d); 

Getopt::Long::Configure(qw(pass_through)); 
GetOptions ('a=s' => \$a, 'b=s' => \$b); 

Getopt::Long::Configure(qw(no_pass_through)); 
GetOptions ('c=s' => \$c, 'd=s' => \$d); 

print "a = $a\nb = $b\nc = $c\nd = $d\n"; 

請注意,您應該確保您的GetOptions的最後調用應該配置no_pass_through以確保您收到有關未知選項的警告。

% perl test_getop.pl -a AA -b BB -c CC -d DD -e EE 
Unknown option: e 
a = AA 
b = BB 
c = CC 
d = DD 
相關問題