windows - Windows cmd 如何在运行 Perl 单行程序时转换命令行?

标签 windows perl shell

我知道 Windows shell 将可执行文件名称后的整行传递给可执行文件,解析它是可执行文件的任务。 例如,

C:\Users\osiv\Desktop\>perl -e "use File::Spec; print $_.' ' foreach (File::Spec->splitdir(\"C:\\Users\\osiv\\\"));"

应该将“perl”之后的所有字符传递给在 %PATH% 值目录中找到的 perl.exe。

向我解释输出

C:\Users\osiv\Desktop\>perl -e "use File::Spec; print $_.' ' foreach (File::Spec->splitdir(\"C:\\Users\\osiv\\\"));"
Can't find string terminator '"' anywhere before EOF at -e line 1.

C:\Users\osiv\Desktop\>perl -e "use File::Spec; print $_.' ' foreach (File::Spec->splitdir(\"C:\\Users\\osiv\\\\"));"
Can't find string terminator '"' anywhere before EOF at -e line 1.

C:\Users\osiv\Desktop\>perl -e "use File::Spec; print $_.' ' foreach (File::Spec->splitdir(\"C:\\Users\\osiv\\\\\"));"
C: Users osiv

我希望 Perl 通过查找应该在开始和结束处有 "的字符串来解析 Windows shell 传递的字符串。我用\"转义它们,并期望例如\"osiv\\\\\"));" 被解析为 osiv\\。但是,\"osiv\\\")); " 没有被解析为 osiv\,那么它实际上是如何被解析的呢?

Explanation of cmd.exe, CreateProcess command line string metacharacters

最佳答案

谁在乎? exact rules are convoluted and hard to remember .只要在你的 Perl 单行中不使用双引号就可以避免这个问题。你知道你有 ' , q{}qq{}可用。

All of cmd’s transformations are triggered by the presence of one of the metacharacters (, ), %, !, ^, ", <, >, &, and |. " is particularly interesting: when cmd is transforming a command line and sees a ", it copies a " to the new command line, then begins copying characters from the old command line to the new one without seeing whether any of these characters is a metacharacter. This copying continues until cmd either reaches the end of the command line, runs into a variable substitution, or sees another ". In the last case, cmd copies a " to the new command line and resumes normal processing. This behavior is almost, but not quite like what CommandLineFromArgvW does with the same character; the difference is that cmd does not know about the \" sequence and begins interpreting metacharacters earlier than we would expect.

还有:

C:\> perl -MFile::Spec::Functions=splitdir -MFile::HomeDir -we "print qq{'$_' } for splitdir home"

'C:' 'Users' 'sinan'

perl -wE "use File::Spec; print \"'$_' \" for File::Spec->splitdir( \"C:\\Users\\osiv\\\\\" )"

'C:' 'Users' 'osiv' ''

这表明您应该省略尾随目录分隔符。

A better method of quoting

While the " metacharacter cannot fully protect metacharacters in our command lines against unintended shell interpretation, the ^ metacharacter can. When cmd transforms a command line and sees a ^, it ignores the ^ character itself and copies the next character to the new command line literally, metacharacter or not. That’s why ^ works as the line continuation character: it tells cmd to copy a subsequent newline as itself instead of regarding that newline as a command terminator. If we prefix with ^ every metacharacter in an argument string, cmd will transform that string into the one we mean to use.

尝试遵循这一点,我能想到的最好的办法是:

perl -wE ^"use File::Spec; print \^"'$_' \^" for File::Spec-^>splitdir^(\^"C:\\Users\\osiv\\\\\^"^) ^"

正如我所说,避免 "在一行中,使用 ' , q{} , 和 qq{} .

关于windows - Windows cmd 如何在运行 Perl 单行程序时转换命令行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38766418/

相关文章:

Windows 10 : Docker exits containers immediately

c++ - Windows 中的 Exe 在调用 GetWindowsDirectory 时 append wstring 时崩溃

perl - 如何替换perl中的空格

linux - 水平连接所有文件且仅连接特定列

bash - 打印所有列,但首先由模式分隔,bash

java - msvcr100.dll丢失错误

c - Microsoft Crypto API 禁止使用 RSAES-OAEP key 传输算法

perl - 在 Ubuntu 16.04LTS 上的 Jupyter notebook 中安装 Perl

perl - Perl中的矩阵矩阵

mysql - 如何修复 MacPorts 安装 MySQL 时的连接错误?