如何从 Raku 命令行获取多个文件名?

问题描述 投票:0回答:4

这个 Raku 程序按我的预期工作:

sub MAIN($name) { say "Got $name" }

我可以在命令行上传递单个名称:

$ raku m1.raku foo
Got foo

但是,明显的扩展,

sub MAIN(@names) { say "Got $_" for @names }

不起作用:

$ raku mm.raku foo
Usage:
  mm.raku <names>
$ raku mm.raku foo bar
Usage:
  mm.raku <names>

我做错了什么?

command-line command-line-arguments raku
4个回答
12
投票

@cjm 说的话。

但是,您可以更进一步,检查您指定的名称是否确实是文件。如果不是,则生成错误消息。诀窍是使用多重调度:

subset File of Str where *.IO.f;

multi sub MAIN(*@files where @files.all ~~ File) {
    say "These are all files: @files.join(",")";
}
multi sub MAIN(*@files) {
    say "These are *NOT* files: @files.grep(* !~~ File).join(",")";
}

如果命令行上指定的所有名称实际上都是文件,则将运行第一个候选者。如果第一个候选没有触发,第二个候选将运行,这意味着并非所有指定的名称实际上都是文件。


11
投票

为此,您必须使用 slurpy array 签名:

sub MAIN(*@names) { say "Got $_" for @names }

按预期工作:

$ raku mm.raku
$ raku mm.raku foo
Got foo
$ raku mm.raku foo bar
Got foo
Got bar

3
投票

有一个特殊的

$*ARGFILES
变量,它提供了一种迭代在命令行上传递到程序的文件的方法。

#!/usr/bin/raku
    
for $*ARGFILES.handles -> $fh {

    say $fh;
}
$ ./enum_files.raku links.txt words.txt 
IO::Handle<"links.txt".IO>(opened)
IO::Handle<"words.txt".IO>(opened)

我们可以使用它的

lines
方法来读取给定文件的行。

#!/usr/bin/raku

.say for $*ARGFILES.lines
$ ./read_lines.raku words.txt words2.txt 
sky
cloud
cup
rock
war
tea
coffee
falcon
...

0
投票

@cjm 的答案最适合您的问题。但正如 Jan 所说,还有另一种方法:

说“得到:”@*ARGS

其中@*ARGS是一个动态变量,定义为命令行上的args。

$*ARGFILES 有一些额外的细微差别。在 main 之外,如果没有参数,则从 @*ARGS 或 $*IN 获取其值。在 main 里面它只是做 $*IN 。

© www.soinside.com 2019 - 2024. All rights reserved.