我知道 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/