首页 > 解决方案 > 如何将 raku -e 和 -n 与多个文件 glob 一起使用

问题描述

我想在 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 上是这样(文档中有一个根本不起作用的示例)。

#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

标签: command-line-argumentsglobrakucommand-line-tool

解决方案


我对文件通配的基本理解是 shell 处理它——而且由于您似乎在 Windows 上,所有的赌注都可能被取消。唯一的例外可能是如果您使用的是WSLWindows-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 ''

我实际上只是*.txt使用上面的命令打印了五 (5) 个文件的内容。该-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 Glossary 的检查表明,设计人员故意将 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等。(此外,无需use IO::Glob;在 Raku 单行中合并一行,它是通过-M已经)。

请参阅以下链接中的Txt::CSV模块和/或模块的 Raku 单线示例:XML

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


推荐阅读