问题描述
如果没有在命令行上给出文件,是否有更优雅的方式来处理来自命令行参数或STDIN
的输入?我目前正在这样做:
sub MAIN(*@opt-files,Bool :$debug,... other named options ...) {
# note that parentheses are mandatory here for some reason
my $input = @opt-files ?? ([~] .IO.slurp for @opt-files) !! $*IN.slurp;
... process $input ...
}
还不错,但是我想知道是否缺少一些更简单的方法吗?
解决方法
我可能会去买multi sub MAIN
,就像这样:
multi sub MAIN(Bool :$debug)
{
process-input($*IN.slurp);
}
multi sub MAIN(*@opt-files,Bool :$debug)
{
process-input($_.IO.slurp) for @opt-files;
}
,
我可能会做两件事来改变这一点。我分手了?? !!放在不同的行上,我将使用完整的方法链:
sub MAIN(*@opt-files,Bool :$debug,... other named options ...) {
my $input = @opt-files
?? @opt-files».IO».slurp.join
!! $*IN.slurp;
... process $input ...
}
您也可以使用@opt-files.map(*.IO.slurp).join
编辑:可以在ugexe's answer上构建
sub MAIN(*@opt-files,... other named options ...) {
# Default to $*IN if not files
@opt-files ||= '-';
my $input = @opt-files».IO».slurp.join
... process $input ...
}
,
我可能希望起作用的是将@*ARGS
设置为签名中的文件名列表。
然后只需使用$*ARGFILES
。
sub MAIN( *@*ARGS,... other named options ...) {
my $input = slurp; # implicitly calls $*ARGFILES.slurp()
... process $input ...
}
但这不起作用。
在使用之前,您可以通过将Rakudo设置为低级别的空值来将其更新为$*ARGFILES
。
sub MAIN( *@*ARGS,... other named options ...) {
{ use nqp; $*ARGFILES := nqp::null }
my $input = slurp;
... process $input ...
}
但这使用的实现细节可能会在将来发生变化。
更好的方法是直接自己直接创建IO :: ArgFiles的新实例。
您甚至可以将其存储在$*ARGFILES
中。然后slurp
自己会吞噬所有文件内容。
sub MAIN( *@opt-files,... other named options ...) {
my $*ARGFILES = IO::ArgFiles.new( @opt-files || $*IN );
my $input = slurp;
... process $input ...
}
请注意,IO :: ArgFiles只是IO :: CatHandle的一个空子类。
因此,您可以改写IO::CatHandle.new( @opt‑files || $*IN )
。