为什么这个 Perl 命令在 Windows 命令行上失败?

为什么这个 Perl 命令在 Windows 命令行上失败?

我正在尝试复制 Perl 命令Ask Ubuntu 上的这个答案在 Windows 命令行环境中。我相信我已经下载了Windows 版 Perl并正确安装了它,所以错误似乎是句法

Linux shell 中的原始命令是:

ls | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' . filename.csv

我认为 Windows 版本应该是:

dir > perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' >> filename.csv

但是,这是我收到的错误:

Invalid switch - "(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg".
'/'' is not recognized as an internal or external command,
operable program or batch file.

在 Windows 中运行此 Perl 命令的正确语法是什么?

答案1

另一个答案是不是正确。如果你这样做,在 cmd 中运行时仍然会出错

C:\Users>dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'
Can't find string terminator "'" anywhere before EOF at -e line 1.
'/'' is not recognized as an internal or external command,
operable program or batch file.

原因是多个问题在命令中

有时甚至会像 或/一样分隔命令参数,但幸运的是,它不适用于这种情况。因此将传递为dir/b/c/dyourcommand/param's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'多个参数如果其中有任何单词分隔符,,在这种情况下,该命令将相当于

perl  -pe  's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2   $3-$4-$5   $6   $   & /'

并且你提出的命令dir > perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' >> filename.csv将被解析为

>>filename.csv >perl dir -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2  $3-$4-$5  $6  $ & /'

因为>file重定向可以出现在任何地方。这会导致Invalid switch - "(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg"你在上面看到的情况,因为这不是有效的切换到dir

这也是为什么Can't find string terminator "'" anywhere before EOF at -e line 1除了 cmd 中的行之外,perl(而不是 cmd)会出现错误的原因,因为第一个参数以 开头,'但没有结尾'。很容易检查它是如何拆分成参数的:

E:\>type testparam.bat
@echo off
:loop
if "%1"=="" goto :exit
echo "%1"
shift
goto :loop
:exit

E:\>testparam -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'
"-pe"
"'s/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2"
"$3-$4-$5"
"$6"
"$"
'/'' is not recognized as an internal or external command,
operable program or batch file.

现在看看输出,注意有趣的事情发生:由于&符号,将结束前一个命令并执行一个不存在的&/'命令,并输出如上所示的错误/'


最好的解决方案是使用电源外壳,您只需稍作修改即可运行该命令,因为单引号也用于 PowerShell 中的引用

ls |% { $_.Name } | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'

ls以及PowerShell 中的dirgci别名Get-ChildItem。并且您需要|%(这是ForEach-Object)来打印对象名称。PowerShell 中的另一种方法是

cmd /c dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'

为了清晰起见,我省略了重定向。输出将打印到 stdout。如果您想将其重定向到文件,只需附加>filename.csv>>filename.csv取决于您是否要覆盖或附加

在 cmd 中运行命令会麻烦得多(而且新代码无论如何都应该使用 PowerShell,因为它长期以来一直是默认选项)

dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2^,$3-$4-$5^,$6^,$^&^/'

在这种情况下,更改'"也可以,但在许多其他情况下它很快就会失效

dir | perl -pe "s/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/"

请注意,即使在 Linux 中,你的命令也是错误的

ls | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' . filename.csv

>filename.csv需要. filename.csv

答案2

Windows|也使用管道符。直接复制命令,但lsdir和替换filename为 费用.csv

由于我没有评论的声誉,因此添加为答案

相关内容