如果可以在命令行上指定配置文件,如何优雅地将Getopt :: Long与配置文件组合在一起

时间:2016-02-07 14:15:45

标签: perl5

我想使用这些规则处理脚本选项:

  1. 可以在命令行或配置文件或两者中提供选项
  2. 使用Getopt :: Long
  3. 完成命令行处理
  4. 命令行上的选项优先于配置文件中的选项
  5. 可以在命令行中指定配置文件
  6. 理想情况下,仅使用核心模块
  7. 如果没有要求4,我可以先处理配置文件,然后再处理命令行,允许后面的选项覆盖之前的选项。优雅。

    但是如果在命令行中指定了配置文件,我需要将其全部丢弃并重新启动,这会使一切都突然变得混乱和复杂。

    这是一个优雅的perl成语吗?

1 个答案:

答案 0 :(得分:1)

规则5使事情复杂化...... 但是,在命令行中通过-M加载的模块在脚本中提到的模块之前加载 - 包括Getopt :: Long。因此,我们可以在默认配置存储在一个简短的自定义模块中进行操作;

# DefaultConf.pm
use strict;
use warnings;

while (<DATA>) {
    chomp ;                              # Remove the newline
    s/ \s* \#.* //x ;                    # Strip comments
    next if / ^ \s* $ /x ;               # Ignore blank lines
    my @a = split(" ", $_, 2);           # Break into 2 pieces and unshift
    unshift(@ARGV, $_) for reverse @a ;  # onto ARGV in reverse order
}

# print "===\n", join(" ", @ARGV), "\n", "===\n";  # debug

1;
__DATA__

# Default App  config data here
--verbose
-n  # single old-style switch with comment

# another comment
--files file1.txt, file2.txt

perl忽略__DATA__之后的文本,但程序员可以通过DATA文件句柄使用。在这里,我们可以使用一个限制存储脚本的默认配置 - 每行只有一个选项(带参数)。注释可以在选项规范的末尾使用,也可以使用perl注释字符用于整行,&#39;#&#39;。

这可以从命令行中使用,如下所示:

perl -MDefaultConf my_app.pl --verbose=0 --files file12.txt --log

my_app.pl正常加载Getopt::Long,但由于我们的自定义模块是通过命令行上的-M加载的,因此首先加载因此,我们可以小提琴在@ARGV获得贪婪的小手之前Getopt::Long。此后,实际选项处理由Getopt::Long完成,因此我们自定义模块末尾的选项语法完全相同。

希望内联注释使代码自我解释 - 唯一的诀窍就是当有两个&#34;件&#34; (比方说,一个选项及其单个参数),我们需要将它们按反向顺序推送到@ARGV的前面(unshift - not push),这样如果相同在命令行中提到了option,它在后面处理,因此优先。

使用此方法,您可以为不同的&#34;运行情况提供大量配置文件&#34;通过-M选项选择,或者根据要求,您可以在没有任何使用CLI选项的情况下运行,或者使用CLI选项优先的组合。

关于规则5的最后评论 - 仅核心模块。由于此限制,您必须使用此(或类似)模块 - NOT 核心模块。虽然它很小且易于理解,但它没有测试,并且它没有被部署在数百个地方,如Config::Tiny所说的那样。 Config::Tiny长度不超过100行(不包括空格和注释),大约一小时就可以完全理解。当然,每个人的环境和限制都是不同的 - 这只是需要考虑的事情。