命令行参数的处理通过内置数组@ARGV实现,该数组包含在启动脚本时传递给脚本的所有参数(不包括脚本本身的名称)。这是任何CLI Perl应用程序的基本方法,但它有许多与数据类型、编码、参数分隔和自动读取文件潜在问题有关的细微差别。
从Perl的早期版本开始,数组@ARGV就作为启动参数的标准“入口点”,类似于C语言中的argv[]。然而,作为一种通用和文本处理语言,Perl增加了许多额外的技巧——例如,表达式<>与@ARGV的内容“相关”,允许同时读取作为参数列出的文件。
简单地读取@ARGV适合基本情况。在复杂的CLI程序中,会出现处理选项(例如--help,-o file)的任务。在这里,按索引简单读取数据变得不安全且不便利。处理包含空格、非标准字符或不同编码的参数时情况更加复杂。此外,还有关于通过操作符<>自动打开文件的问题,以及如果@ARGV的元素如“ - ”(stdin)相等时的意外行为。
读取简单参数:
foreach my $arg (@ARGV) { print "Arg: $arg "; }
通常,对于选项,使用特定模块Getopt::Long:
use Getopt::Long; my $help; GetOptions('help' => \$help);
要读取@ARGV中的所有文件,可以通过循环直接读取文件内容:
while (<>) { print; }
@ARGV解释为待读取的文件列表如果一个命令行参数仅包含破折号(-)会发生什么?
在这种情况下,使用操作符<>时,Perl将'-'视为标准输入(stdin),而不是文件名。
perl script.pl - file.txt # 首先从stdin读取,然后从file.txt读取
可以安全地在脚本中修改@ARGV吗?
可以,这是删除已经处理的参数的标准做法。通常在处理选项后,@ARGV只保留“干净”的文件名或未识别的参数。
在处理UTF-8参数时,需要在@ARGV中进行编码/解码吗?
这取决于区域设置和环境。默认情况下,Perl不会转换@ARGV的编码,而是“按原样”接受。因此,如果文件名(或参数)包含非ASCII字符,建议明确使用Encode对字符串进行解码,以便在Perl中处理它们。
解析日志的工具接受文件列表。用户不小心指定了'-':
perl parse.pl - access.log
结果是程序突然停滞,等待键盘输入。
优点:
缺点:
CLI程序通过Getopt::Long读取参数,明确处理所有负号选项,只在@ARGV中保留文件名:
perl report.pl --input access.log --output report.txt
优点:
缺点: