我正在尝试复制 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.
原因是多个问题在命令中
- 单引号
'
是不是cmd.exe 中的引号符号 - 逗号
,
、分号;
和等号=
也是分隔符与其他 shell 一样,在空格和制表符旁边
有时甚至会像 或/
一样分隔命令参数,但幸运的是,它不适用于这种情况。因此将传递为dir/b/c/d
yourcommand/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 中的dir
和gci
别名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|
也使用管道符。直接复制命令,但ls
用dir
和替换filename
为 费用.csv
由于我没有评论的声誉,因此添加为答案