简体   繁体   English

转义参数中的双引号

[英]Escape double quotes in parameter

In Unix I could run myscript '"test"' and I would get "test" .在 Unix 中,我可以运行myscript '"test"'并得到"test"

In Windows cmd I get 'test' .在 Windows cmd我得到'test'

How can I pass double-quotes as a parameter?如何将双引号作为参数传递? I would like to know how to do this manually from a cmd window so I don't have to write a program to test my program.我想知道如何从cmd窗口手动执行此操作,因此我不必编写程序来测试我的程序。

Another way to escape quotes (though probably not preferable), which I've found used in certain places is to use multiple double-quotes .我发现在某些地方使用的另一种转义引号的方法(尽管可能不是可取的)是使用多个双引号 For the purpose of making other people's code legible, I'll explain.为了让其他人的代码清晰易读,我会解释一下。

Here's a set of basic rules:这是一组基本规则:

  1. When not wrapped in double-quoted groups, spaces separate parameters:当不包含在双引号组中时,空格分隔参数:
    program param1 param2 param 3 will pass four parameters to program.exe : program param1 param2 param 3将传递四个参数给program.exe
    param1 , param2 , param , and 3 . param1param2param3
  2. A double-quoted group ignores spaces as value separators when passing parameters to programs:将参数传递给程序时,双引号组会忽略空格作为值分隔符:
    program one two "three and more" will pass three parameters to program.exe : program one two "three and more"将传递三个参数给program.exe
    one , two , and three and more . onetwothree and more
  3. Now to explain some of the confusion: 现在解释一些混淆:
  4. Double-quoted groups that appear directly adjacent to text not wrapped with double-quotes join into one parameter:直接出现在未用双引号包裹的文本旁边的双引号组加入一个参数:
    hello"to the entire"world acts as one parameter: helloto the entireworld . hello"to the entire"world作为一个参数: helloto the entireworld
  5. Note: The previous rule does NOT imply that two double-quoted groups can appear directly adjacent to one another. 注意:上一条规则并不意味着两个双引号组可以直接相邻出现。
  6. Any double-quote directly following a closing quote is treated as (or as part of) plain unwrapped text that is adjacent to the double-quoted group, but only one double-quote:紧跟在结束引号之后的任何双引号都被视为(或作为)与双引号组相邻的普通解包文本,但只有一个双引号:
    "Tim says, ""Hi!""" will act as one parameter: Tim says, "Hi!" "Tim says, ""Hi!"""将作为一个参数: Tim says, "Hi!"

Thus there are three different types of double-quotes: quotes that open, quotes that close, and quotes that act as plain-text.因此,存在三种不同类型的双引号:打开的引号、关闭的引号和充当纯文本的引号。
Here's the breakdown of that last confusing line:这是最后一个令人困惑的行的细分:

"   open double-quote group
T   inside ""s
i   inside ""s
m   inside ""s
    inside ""s - space doesn't separate
s   inside ""s
a   inside ""s
y   inside ""s
s   inside ""s
,   inside ""s
    inside ""s - space doesn't separate
"   close double-quoted group
"   quote directly follows closer - acts as plain unwrapped text: "
H   outside ""s - gets joined to previous adjacent group
i   outside ""s - ...
!   outside ""s - ...
"   open double-quote group
"   close double-quote group
"   quote directly follows closer - acts as plain unwrapped text: "

Thus, the text effectively joins four groups of characters (one with nothing, however):因此,文本有效地连接了四组字符(但是,一组没有任何字符):
Tim says, is the first, wrapped to escape the spaces Tim says,是第一个,包裹着逃离空间
"Hi! is the second, not wrapped (there are no spaces) "Hi!是第二个,没有包裹(没有空格)
is the third, a double-quote group wrapping nothing是第三个,一个不包含任何内容的双引号组
" is the fourth, the unwrapped close quote. "是第四个,展开的结束引号。

As you can see, the double-quote group wrapping nothing is still necessary since, without it, the following double-quote would open up a double-quoted group instead of acting as plain-text.正如您所看到的,双引号组仍然需要什么都不包裹,因为如果没有它,下面的双引号将打开一个双引号组,而不是充当纯文本。

From this, it should be recognizable that therefore, inside and outside quotes, three double-quotes act as a plain-text unescaped double-quote:由此,应该可以看出,因此,内外引号,三个双引号充当纯文本未转义双引号:

"Tim said to him, """What's been happening lately?""""

will print Tim said to him, "What's been happening lately?" Tim said to him, "What's been happening lately?" as expected.正如预期的那样。 Therefore, three quotes can always be reliably used as an escape.因此,始终可以可靠地将三个引号用作转义符。
However, in understanding it, you may note that the four quotes at the end can be reduced to a mere two since it technically is adding another unnecessary empty double-quoted group.但是,在理解它时,您可能会注意到末尾的四个引号可以减少到仅仅两个,因为它在技术上添加了另一个不必要的空双引号组。

Here are a few examples to close it off:以下是一些关闭它的示例:

program a b                       REM sends (a) and (b)
program """a"""                   REM sends ("a")
program """a b"""                 REM sends ("a) and (b")
program """"Hello,""" Mike said." REM sends ("Hello," Mike said.)
program ""a""b""c""d""            REM sends (abcd) since the "" groups wrap nothing
program "hello to """quotes""     REM sends (hello to "quotes")
program """"hello world""         REM sends ("hello world")
program """hello" world""         REM sends ("hello world")
program """hello "world""         REM sends ("hello) and (world")
program "hello ""world"""         REM sends (hello "world")
program "hello """world""         REM sends (hello "world")

Final note: I did not read any of this from any tutorial - I came up with all of it by experimenting.最后说明:我没有从任何教程中阅读任何内容 - 我通过实验想出了所有内容。 Therefore, my explanation may not be true internally.因此,我的解释在内部可能并不正确。 Nonetheless all the examples above evaluate as given, thus validating (but not proving) my theory.尽管如此,上面的所有示例都按照给定的方式进行评估,从而验证(但不是证明)我的理论。

I tested this on Windows 7, 64bit using only *.exe calls with parameter passing (not *.bat, but I would suppose it works the same).我仅使用带有参数传递的 *.exe 调用(不是 *.bat,但我认为它的工作原理相同)在 64 位 Windows 7 上对此进行了测试。

Try this:尝试这个:

myscript """test"""

"" escape to a single " in the parameter. "" 转义到参数中的单个 "。

I cannot quickly reproduce the symptoms: if I try myscript '"test"' with a batch file myscript.bat containing just @echo.%1 or even @echo.%~1 , I get all quotes: '"test"'我无法快速重现这些症状:如果我使用仅包含@echo.%1甚至@echo.%~1的批处理文件myscript.bat尝试myscript '"test"' ,我会得到所有引号: '"test"'

Perhaps you can try the escape character ^ like this: myscript '^"test^"' ?也许您可以像这样尝试转义字符^myscript '^"test^"'

The 2nd document quoted by Peter Mortensen in his comment on the answer of Codesmith made things much clearer for me. Peter Mortensen 在他对 Codesmith 回答的评论中引用的第二份文件让我更清楚地了解情况。 That document was written by windowsinspired.com.该文档由 windowsinspired.com 编写。 The link repeated: A Better Way To Understand Quoting and Escaping of Windows Command Line Arguments .链接重复: 一个更好的方法来理解 Windows 命令行参数的引用和转义

Some further trial and error leads to the following guideline:一些进一步的试验和错误导致以下准则:

Escape every double quote " with a caret ^ . If you want other characters with special meaning to the Windows command shell (eg, < , > , | , & ) to be interpreted as regular characters instead, then escape them with a caret, too.使用插入符号^转义每个双引号" 。如果您希望其他对 Windows 命令外壳具有特殊含义的字符(例如<>|& )被解释为常规字符,那么也可以使用插入符号对它们进行转义.

If you want your program foo to receive the command line text "a\\"bc" > d and redirect its output to file out.txt , then start your program as follows from the Windows command shell:如果您希望您的程序foo接收命令行文本"a\\"bc" > d并将其输出重定向到文件out.txt ,请按如下方式从 Windows 命令外壳启动您的程序:

foo ^"a\^"b c^" ^> d > out.txt

If foo interprets \\" as a literal double quote and expects unescaped double quotes to delimit arguments that include whitespace, then foo interprets the command as specifying one argument a"bc , one argument > , and one argument d .如果foo\\"解释为字面双引号并期望未转义的双引号分隔包含空格的参数,则foo会将命令解释为指定一个参数a"bc 、一个参数>和一个参数d

If instead foo interprets a doubled double quote "" as a literal double quote, then start your program as相反,如果foo将双双引号""解释为文字双引号,则将程序启动为

foo ^"a^"^"b c^" ^> d > out.txt

The key insight from the quoted document is that, to the Windows command shell, an unescaped double quote triggers switching between two possible states.引用文档的关键见解是,对于 Windows 命令外壳,未转义的双引号会触发两种可能状态之间的切换。

Some further trial and error implies that in the initial state, redirection (to a file or pipe) is recognized and a caret ^ escapes a double quote and the caret is removed from the input.一些进一步的试验和错误意味着在初始状态下,重定向(到文件或管道)被识别并且插入符号^转义双引号并且插入符号从输入中删除。 In the other state, redirection is not recognized and a caret does not escape a double quote and isn't removed.在另一种状态下,无法识别重定向并且插入符号不会转义双引号并且不会被删除。 Let's refer to these states as 'outside' and 'inside', respectively.让我们分别将这些状态称为“外部”和“内部”。

If you want to redirect the output of your command, then the command shell must be in the outside state when it reaches the redirection, so there must be an even number of unescaped (by caret) double quotes preceding the redirection.如果要重定向命令的输出,则命令外壳在到达重定向时必须处于外部状态,因此在重定向之前必须有偶数个未转义(插入符号)的双引号。 foo "a\\"b " > out.txt won't work -- the command shell passes the entire "a\\"b " > out.txt to foo as its combined command line arguments, instead of passing only "a\\"b " and redirecting the output to out.txt . foo "a\\"b " > out.txt不起作用——命令外壳将整个"a\\"b " > out.txt作为其组合命令行参数传递给foo ,而不是只传递"a\\"b "并将输出重定向到out.txt

foo "a\\^"b " > out.txt won't work, either, because the caret ^ is encountered in the inside state where it is an ordinary character and not an escape character, so "a\\^"b " > out.txt gets passed to foo . foo "a\\^"b " > out.txt也不起作用,因为插入符号^是在内部状态遇到的,它是普通字符而不是转义字符,所以"a\\^"b " > out.txt被传递给foo

The only way that (hopefully) always works is to keep the command shell always in the outside state, because then redirection works. (希望)始终有效的唯一方法是将命令外壳始终保持在外部状态,因为这样重定向就起作用了。

If you don't need redirection (or other characters with special meaning to the command shell), then you can do without the carets.如果您不需要重定向(或其他对命令 shell 具有特殊含义的字符),那么您可以不用插入符号。 If foo interprets \\" as a literal double quote, then you can call it as如果foo\\"解释为文字双引号,那么您可以将其称为

foo "a\"b c"

Then foo receives "a\\"bc" as its combined arguments text and can interpret it as a single argument equal to a"bc .然后foo接收"a\\"bc"作为其组合参数文本,并且可以将其解释为等于a"bc的单个参数。

Now -- finally -- to the original question.现在 - 最后 - 到最初的问题。 myscript '"test"' called from the Windows command shell passes '"test"' to myscript .从 Windows 命令外壳调用的myscript '"test"''"test"'传递给myscript Apparently myscript interprets the single and double quotes as argument delimiters and removes them.显然myscript将单引号和双引号解释为参数分隔符并删除它们。 You need to figure out what myscript accepts as a literal double quote and then specify that in your command, using ^ to escape any characters that have special meaning to the Windows command shell.您需要弄清楚myscript接受什么作为文字双引号,然后在您的命令中指定它,使用^转义任何对 Windows 命令外壳具有特殊含义的字符。 Given that myscript is also available on Unix, perhaps \\" does the trick. Try鉴于myscript在 Unix 上也可用,也许\\"可以解决问题。试试

myscript \^"test\^"

or, if you don't need redirection,或者,如果您不需要重定向,

myscript \"test\"

I'm calling powershell from cmd, and passing quotes and neither escapes here worked.我正在从 cmd 调用 powershell,并传递引号,这里没有任何转义。 The grave accent worked to escape double quotes on this Win 10 surface pro.在这个 Win 10 Surface Pro 上,重音可以避免双引号。

>powershell.exe "echo la`"" >> test
>type test
la"

Below are outputs I got for other characters to escape a double quote:以下是我为其他字符转义双引号得到的输出:

la\
la^
la
la~

Using another quote to escape a quote resulted in no quotes.使用另一个引号来转义引号导致没有引号。 As you can see, the characters themselves got typed, but didn't escape the double quotes.如您所见,字符本身被输入,但没有转义双引号。

In Unix I could run myscript '"test"' and I would get "test" .在Unix中,我可以运行myscript '"test"'然后得到"test"

In Windows cmd I get 'test' .在Windows cmd我得到'test'

How can I pass double-quotes as a parameter?如何传递双引号作为参数? I would like to know how to do this manually from a cmd window so I don't have to write a program to test my program.我想知道如何从cmd窗口手动执行此操作,因此我不必编写程序来测试程序。

Maybe you came here, because you wonder how to escape quotes that you need in the command that you pass to /c on cmd.exe ?也许您来到这里,因为您想知道如何在传递给/c on cmd.exe的命令中转义所需的引号? Well you don't:好吧,您不会:

CMD /c "MKDIR "foo bar""

will execute将执行

MKDIR "foo bar"

which is really a behavior that I did not expect in the first glance.这确实是我第一眼没想到的行为。 Inconsistency at its glance.一目了然的不一致。

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

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