调用两次Perl GetOptions无法按预期工作

3
我很难找到一个解释这种行为的Perl GetOptions参考文献。如果我调用GetOptions两次,那么第二次调用它时,它将无法解析命令行参数,并且它们都将返回未定义值。第一次对GetOptions的调用(顺便说一下,失败并返回0)是否吃掉了命令行参数,或者第二次调用只是决定不再尝试解析,因为它记得之前已经失败了?请不要问我为什么要调用GetOptions两次--因为重构代码会很复杂,除非必要,否则我宁愿不这样做。我只想在“真正”的GetOptions调用之前简单地测试是否存在单个命令行参数。谢谢。

看看 Penfold 在我的回答中的评论。那可能正是你所需要的。 - Cascabel
3个回答

8

GetOptions函数会消耗并修改@ARGV数组。在调用该函数后,通常只剩下文件名参数。

如果您不存储数组的副本以便稍后重置它,则后续的GetOptions调用将无法解析任何内容。您可以尝试使用任意数组调用GetOptionsFromArray而不是使用隐式的@ARGV


5
GetOptions函数从@ARGV中删除选项,只留下实际的参数,这样当处理@ARGV时,程序的其余部分不必考虑选项。我没有在文档中明确提到这一点,但这是选项解析器通常工作的方式。
这意味着第二次调用它将是相当无用的,除非您有一些像这样的复杂选项模式:--section1-opt1 --section1-opt2 -- --section2-opt1 --section1-opt2 --<real arguments>。第一次调用会吃掉第一个终止的--,第二次会解析下一节,直到第二个--。虽然我无法想象这是友好的界面。

5
请使用最新的Getopt::Long,然后执行"use Getopt::Long qw/pass_through/;”- 您对GetOptions的第一个调用将仅从@ARGV中删除它知道的选项,而不是所有选项。 - Penfold

3

正如已经指出的GetOptions会修改@ARGV。虽然不太美观,但你可以将@ARGV声明为本地变量:

{
local(@ARGV) = @ARGV;
GetOptions(...);
}

# @ARGV "restored" here    
GetOptions(...);

3
目前最好只需复制 @ARGV 并使用 GetOptionsFromArray - 这样更清晰易懂。 - Cascabel
@Jefromi,我没有提到这一点(虽然可能应该),因为OP说,代码“过于复杂,无法重构”。 - Linus Kleen
OP所指的重构是完全消除一个调用。将GetOptions(...)更改为my @foo = @ARGV; GetOptionsFromArray(\@foo, ...);并不是一种重构,就像声明@ARGV为本地变量一样。 - Cascabel
感谢所有的反馈,谢谢。我觉得我会测试ARGV的内容以找到我所需的一个参数,而不是尝试调用两次GetOptions。 - jarmod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接