如何将 raku -e 和 -n 与多个文件 glob 一起使用

Ger*_*ill 10 glob command-line-tool command-line-arguments raku

我想在 Windows 上的 raku 中执行以下操作

raku -n -e ".say if /mydatabegin/;" *.file
Run Code Online (Sandbox Code Playgroud)

无法打开文件 C:\..\*.file: 参数无效

glob 不被解释为 glob。我认为这是因为 Windows 要求你的程序自己进行通配?那么是否有一个预处理指令或函数,甚至是我可能错过或重定向的开关,或者允许扩展 glob 同时保持 -n (或 -p)和 -e 开关的简单性的东西?

显然,我可以通过删除 -n (或 -p)将其更改为完整程序,只需使用 -e 指定 main 并循环 glob 结果。但我真的很喜欢-n。

附言。我实际上只是在学习 raku,并且很惊讶这并没有开箱即用。因此,具有简单语法的完整程序的示例也可以工作。但我真的很喜欢-n..

编辑:回复@chenyf

raku -e ".say for $*ARGFILES" *.file
Run Code Online (Sandbox Code Playgroud)

同样的错误。有关的:

raku -e ".say for $*ARGFILES.lines" *.file
Run Code Online (Sandbox Code Playgroud)

同样的错误。

raku -e "use IO::Glob; .say for glob('*.file')"
Run Code Online (Sandbox Code Playgroud)

按预期工作!扩展:

raku -e "use IO::Glob; .say for glob('*.file').lines"
Run Code Online (Sandbox Code Playgroud)

对于“IO::Glob”类型的调用者没有这样的方法“lines”

越来越接近——也许对此进行扩展是一个足够好的解决方法。但回到一线荣耀的尝试:

raku -e "use IO::Glob; .say for glob($*ARGFILES)" test.file
Run Code Online (Sandbox Code Playgroud)

无法解析调用者 glob(IO::ArgFiles:D); 这些签名都不匹配。

好吧——让我们回到安全的字符串:

raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" test.file
Run Code Online (Sandbox Code Playgroud)

是的!所以..:

raku -e "use IO::Glob; .say for glob($*ARGFILES.Str).lines" test.file
Run Code Online (Sandbox Code Playgroud)

对于“IO::Glob”类型的调用者没有这样的方法“lines”

我显然需要阅读更多手册。但让我们退一步看看我的用例是否有效:

raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" *.file
Run Code Online (Sandbox Code Playgroud)

无法打开文件 C:\..\*.file: 参数无效

我一开始就犯了同样的错误。这可能只是 Windows 上的 raku 错误吗?

编辑:

raku -MIO::Glob -e "my @files = (map { glob($_).dir }, @*ARGS).flat; for @files -> $file { say $_ for $file.lines }" *file *file2 *5
Run Code Online (Sandbox Code Playgroud)

我有三组文件。我几乎可以接受这个解决方案 - 除了由于某种原因这些行被打印为“s

关于缩短和去掉引号有什么想法吗?

编辑解决 $*ARGFILES 变量的自动通配问题:

raku -MIO::Glob -n -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say" *.file *.file2
Run Code Online (Sandbox Code Playgroud)

这样做的优点是看起来仍然像原来的衬里一样;它使用-n!它只需要执行在创建 $*ARGFILES 时似乎是一个错误的通配符。

raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say for $*ARGFILES.lines" *.file *.file2
Run Code Online (Sandbox Code Playgroud)

上面转换为 $*ARGFILES.lines 表明 $*ARGFILES 从 @*ARGS 动态获取其值。

编辑

最后,事实证明 glob 函数不适用于目录,至少在 Windows 上(文档中有一个根本不起作用的示例)。

#Example from https://github.com/zostay/raku-IO-Glob
for glob("src/core/*.pm") -> $file { say ~$file }

#mine that doesn't work
raku -MIO::Glob -e "for glob('..\*.file') -> $file { say ~$file }"

#mine that does work.
raku -MIO::Glob -e "for glob('*.file').dir('..') -> $file { say ~$file }"

#And therefore the final modification of the script above:
raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS).flat };  .say for $*ARGFILES.lines" ..\*.file
Run Code Online (Sandbox Code Playgroud)

Ger*_*ill 1

一般答案 - 这不是一个错误。如果 Windows 程序想要的话,就必须处理它们自己的通配符。让它在 raku 可执行文件中工作对我来说很有意义;它消除了特定于平台的意外,并使单行文字变得更容易。

但其他人并不这么认为,有一个足够简单的解决方案——创建自己的模块,这样代码就可以保持一致并且调用相对简单。

这是一个适合初学者的模块。有空间可以添加诸如

  • 强制匹配成功的开关
  • 指示失败的 glob 应保留在 @*ARGS 变量中的开关
  • 切换到仅在其后的 glob 。
  • 应用通配符而不是自动执行的例程。这将允许您删除非文件开关
  • 将每个 glob 收集到自己的列表中(可能使用开关)。

该模块:

unit module CLGlob:ver<1.0>:auth<pureabsolute>;

use IO::Glob;

@*ARGS = map { .Str }, (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS ).flat;
Run Code Online (Sandbox Code Playgroud)

注意:当 glob 函数适用于带有目录的窗口时,可以简化第二个映射中的表达式。

注意:我将每个元素转换为 .Str 以使 @*ARGS 一致。$*ARGFILES 无需执行此操作即可工作,因此如果您不再查看 @*ARGS,则可以保存一些处理。

最后,最终结果:

raku -MCLGlob -ne ".say" ..\*.file ..\*.file2
Run Code Online (Sandbox Code Playgroud)

耶。