【问题标题】:How do I use raku -e and -n with multiple file glob如何将 raku -e 和 -n 与多个文件 glob 一起使用
【发布时间】:2021-11-21 20:30:53
【问题描述】:

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

raku -n -e ".say if /mydatabegin/;" *.file

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

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

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

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

编辑:回复@chenyf

raku -e ".say for $*ARGFILES" *.file

同样的错误。相关:

raku -e ".say for $*ARGFILES.lines" *.file

同样的错误。

raku -e "use IO::Glob; .say for glob('*.file')"

按预期工作!展开:

raku -e "use IO::Glob; .say for glob('*.file').lines"

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

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

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

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

好的 - 让我们回到字符串的安全性:

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

是的!所以..:

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

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

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

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

打开文件 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

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

关于缩短和去掉引号的任何想法?

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

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

这样做的好处是看起来仍然像原来的一个班轮;它使用-n!在创建 $*ARGFILES 时,它只需要执行似乎是错误的 globbing。

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

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

编辑

最后,glob 函数不适用于目录,至少在 Windows 上是这样(documentation 有一个根本不起作用的示例)。

#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

【问题讨论】:

  • 也许$*ARGFILES 有帮助,例如:andrewshitov.com/2018/12/24/…
  • 编辑了答案以显示使用 $*ARGFILES 进行测试。
  • 顺便说一句,感谢 chenyf 的链接 - 我确实检查了它,他的例子刻意避免了多个文件,更不用说 globbing。我确实在 cmets 中留下了一个问题。
  • raku -e '$*ARGFILES.lines.say;' *.txtraku -e '.say for $*ARGFILES.lines;' *.txt 在我的旧 MacOS 系统上工作。第一个单行在一行中返回每个 *.txt 文件,第二个单行返回与 cat 无法区分的逐行返回(每个从我的当前目录返回五个 *.txtfiles)。
  • 可能是 Window 的(目录)权限错误?还是指定的文件路径不正确?代码raku -ne ".say if /mydatabegin/;" *.txt 在这里工作正常(注意初始. 点)。

标签: command-line-arguments glob raku command-line-tool


【解决方案1】:

我对文件通配的基本理解是 shell 处理它——而且由于您似乎在 Windows 上,所有的赌注都可能被取消。唯一的例外可能是您使用的是WSL Windows-Subsystem-for-Linux,这应该会给您带来更像 Unix/Linux 的体验:

https://docs.microsoft.com/en-us/windows/wsl/about

根据下面的微软文档,Windows有两个内置的shell,CMD.exe和Powershell(我相信上面的WSL shell是可选的):

“命令外壳概述”

“Windows 有两个命令 shell:命令 shell 和 PowerShell。每个 shell 都是一个软件程序,可在您与操作系统或应用程序之间提供直接通信,提供自动化 IT 操作的环境。”

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands


下面是在相当老的bash/MacOS 系统上工作的内容。 使用-ne(非自动打印)命令行标志:

raku -ne 'print $_ ~ "\n";'
raku -ne 'say $_ ;' 
raku -ne '.say;'

使用-pe(自动打印)命令行标志:

raku -pe 'print "";'
raku -pe ''

我实际上只是使用上面的命令打印了五 (5) 个*.txt 文件的内容。 -e 标志总是结束你的命令行标志簇,但可以组合(见下面的-M标志例外)。

现在因为您使用的是 Windows,您可能必须将 "" 双引号替换为 '' 单引号(反之亦然!)。但希望这能让你开始。 [任何其他问题,您可能必须指定 Rakudo 可执行文件的完整路径]。

如果您希望 Raku 为您处理目录转换,可以使用 Raku 的 dir() 命令,该命令可以与其 :test 副词(参数)一起使用。在上述目录中与五 (5) 个 *.txt 文本文件进行比较,(删除 .elems 调用以打印实际文本):

raku -e '.lines.elems.say for dir(test => / \.txt $ /);'
14
16
34
1
16

对比:

raku -e '.lines.elems.say for $*ARGFILES;' *.txt
81

https://docs.raku.org/routine/dir


附录:我对 Raku P5-to-P6 词汇表的检查表明,设计人员故意将 Perl5 的 glob 函数从 Perl6/Raku 中移除,而选择了更强大的内置 dir() 例程。以下链接:

https://docs.raku.org/language/5to6-perlfunc#index-entry-glob_-_perlfunc https://docs.raku.org/routine/dir

Raku 模块 IO::Glob 是非核心的(而且..我从未尝试过)。但是如果你在命令行工作并且想要加载一个模块,你可以使用(例如)-MIO::Glob 后跟-e-ne-pe 等。(另外,不需要合并Raku 单行中的 use IO::Glob; 行,它已通过 -M 加载)。

在下面的链接中查看带有Txt::CSV 模块和/或XML 模块的 Raku 单行示例:

https://unix.stackexchange.com/search?q=%5Bcsv%5D+Raku
https://unix.stackexchange.com/search?q=%5Bxml%5D+Raku

关注下面的其他 Windows CMD.exe 讨论/解决方案:

https://github.com/rakudo/rakudo/issues/4550

【讨论】:

  • 上面包含了看起来很奇怪的raku -pe 'print "";',因为它可以很容易地修改为为您的文件添加行号:raku -pe 'print ++$,"\t";' *.txtraku -pe 'print ++$~"\t";' *.txt跨度>
  • 谢谢@jubilatious1 首先,它必须在 Windows 上,所以我仍在解决 Windows 问题。其次,一旦编写了脚本/程序,我不想更改代码,这就是我使用 *.files 的原因。
  • 就像你的 ".lines.say @files" 构造 - 但是它打印括号和引号。 ARRG。
  • @GerardONeill 我一直在通过Unix & Linux 回答 Raku 中常见的文本处理问题,只需在顶部的框中搜索“Raku”即可。如果您偶尔看到带有额外括号和引号的 Raku 单行答案,请删除对 .raku 和/或 .perl 的所有调用。我会不时包含这些调用以可视化\n 换行符等。
  • 仅供参考 - 与 .say 相比,.put 不打印括号。关于 Str 方法与 gist 方法的区别。
【解决方案2】:

一般答案 - 这不是错误。如果需要,Windows 程序必须处理自己的 globbing。让它在 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;

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

注意:我将每个元素转换为 .Str 以使 @*ARGS 保持一致。 $*ARGFILES 无需这样做就可以工作,因此如果您再也不会查看 @*ARGS,可以节省一些处理。

最后,最终结果:

raku -MCLGlob -ne ".say" ..\*.file ..\*.file2

是的。

【讨论】:

  • 您已编辑您的 OP 以声明 IO::Glob 模块的示例代码不起作用。您是否在适当的 repo 中打开了 Github 上的问题?
  • 还没有。我承认我已经在这上面花了太多时间。但我最终会的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
相关资源
最近更新 更多