简体   繁体   English

使用 cmd /c “echo” 时对双引号的奇怪处理

[英]weird handling of double quotes when using cmd /c “echo”

I'm trying to escape some calls in bat file and I found out that I don't understand even on simple example the weird handling of double quotes:我试图逃避 bat 文件中的一些调用,我发现即使在简单的例子中我也不明白双引号的奇怪处理:

Try尝试

cmd /c "echo " "%TEMP%"                   rem this gives: " "C:\Users\xyz\AppData\Local\Temp
cmd /c "echo" "%TEMP%"                    rem this gives: The filename, directory name, or volume label syntax is incorrect.
cmd /c "echo beg "TEMP" %TEMP%"           rem this gives: beg "TEMP" C:\Users\xyz\AppData\Local\Temp
cmd /c "echo beg ^"TEMP^" %TEMP%"         rem this gives: beg "TEMP" C:\Users\xyz\AppData\Local\Temp
cmd /c "echo beg \"TEMP\" %TEMP%"         rem this gives: beg \"TEMP\" C:\Users\xyz\AppData\Local\Temp

Just open command prompt (cmd.exe) and paste code.只需打开命令提示符 (cmd.exe) 并粘贴代码。 The results are the same when copy/paste to cmd.exe or running a bat file.复制/粘贴到 cmd.exe 或运行 bat 文件时,结果相同。

What I would expect is that cmd /c "echo beg \"TEMP\" %TEMP%" should work correcctly.我期望的是cmd /c "echo beg \"TEMP\" %TEMP%"应该可以正常工作。 At least according to http://daviddeley.com/autohotkey/parameters/parameters.htm#WIN .至少根据http://daviddeley.com/autohotkey/parameters/parameters.htm#WIN

But I don't understand output from all the samples.但是我从所有样本中都不了解 output 。 Anybody could explain me that behaviour?任何人都可以向我解释这种行为吗?


Edit :编辑

The site I'm referencing just explains how arguments are parsed on Windows.我引用的站点只是解释了如何在 Windows 上解析 arguments。 Eg http://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES例如http://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES

What is my expected output?我的预期 output 是多少? I just want to know how that passing of double quotes work.我只想知道双引号的传递是如何工作的。 Later I'd like to construct command lines like this one:后来我想构建这样的命令行:

pwsh -noprofile -command "produceSomeStringsToFind | % { rg -g testfile* \" $_ some string that ends with quote\\\"" . }"

where rg is https://github.com/BurntSushi/ripgrep - where the \" $_ some string that ends with quote\\\"" part is regular expression where I need to escape the quotes.其中rghttps://github.com/BurntSushi/ripgrep - 其中\" $_ some string that ends with quote\\\""部分结尾是正则表达式,我需要在其中转义引号。

From the help text of cmd /?来自cmd /?的帮助文本:

 [...] If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line, where the following logic is used to process quote (") characters: 1. If all of the following conditions are met, then quote characters on the command line are preserved: - no /S switch - exactly two quote characters - no special characters between the two quote characters, where special is one of: &<>()@^| - there are one or more whitespace characters between the two quote characters - the string between the two quote characters is the name of an executable file. 2. Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. [...]

It becomes clear that you are facing the situation explained in section 2. , because echo is not an executable file but an internal command.很明显,您正面临第2.节中解释的情况,因为echo不是可执行文件而是内部命令。 So if the first character is a " , it becomes removed and so becomes the last " , and all the other characters are preserved.因此,如果第一个字符是" ,它将被删除,因此成为最后一个" ,并且所有其他字符都被保留。


Now let us go through your command lines.现在让我们通过您的命令行 go。 So after being parsed and processed by cmd /c :所以经过cmd /c解析处理后:

  1. cmd /c "echo " "%TEMP%" becomes echo " "C:\Users\xyz\AppData\Local\Temp . cmd /c "echo " "%TEMP%"变为echo " "C:\Users\xyz\AppData\Local\Temp
  2. cmd /c "echo" "%TEMP%" becomes echo" "C:\Users\xyz\AppData\Local\Temp ; cmd /c "echo" "%TEMP%"变成echo" "C:\Users\xyz\AppData\Local\Temp ; then the command echo" is tried to be executed, but which is not a valid one, hence it fails.然后命令echo"被尝试执行,但它不是一个有效的,因此它失败了。
  3. cmd /c "echo beg "TEMP" %TEMP%" becomes echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp . cmd /c "echo beg "TEMP" %TEMP%"变为echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp
  4. cmd /c "echo beg ^"TEMP^" %TEMP%" becomes echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp , because escaping with ^ happens even before cmd /c is executed, so it receives the already escaped literal " characters. cmd /c "echo beg ^"TEMP^" %TEMP%" becomes echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp , because escaping with ^ happens even before cmd /c is executed, so it receives已经转义的文字"字符。
  5. cmd /c "echo beg \"TEMP\" %TEMP%" becomes echo beg \"TEMP\" C:\Users\xyz\AppData\Local\Temp , because the \ is nothing special to cmd . cmd /c "echo beg \"TEMP\" %TEMP%"变成echo beg \"TEMP\" C:\Users\xyz\AppData\Local\Temp ,因为\对于cmd \ 没什么特别的

If you want to output the text "%TEMP%" (including the quotes), yo could do this:如果你想 output 文本"%TEMP%" (包括引号),你可以这样做:

rem // This preserves all quotes, because the first character is not such:
cmd /c echo "%TEMP%"
rem // This removes the outer-most pair of quotes, because the first character is such:
cmd /c "echo "%TEMP%""
rem /* This removes the outer-most pair of quotes too, since `cmd /c` receives the already
rem    escaped `"`; however, this could be useful to hide these quotes from the hosting
rem    `cmd` instance, which avoids issues when `%TEMP%` contains special characters
rem    (like `&` or `^`), which you would otherwise have to individually escape: */
cmd /c ^"echo "%TEMP%"^"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM