转义参数中的双引号

在 Unix 中,我可以运行 myscript '"test"',然后得到 "test"

在 Windows cmd中我得到 'test'

如何将双引号作为参数传递?我想知道如何从 cmd窗口手动做到这一点,所以我不必编写程序来测试我的程序。

216606 次浏览

我不能很快重现这些症状: 如果我尝试使用一个只包含 @echo.%1甚至 @echo.%~1的批处理文件 myscript '"test"',我会得到所有引号: '"test"'

也许你可以像这样试试转义字符 ^: myscript '^"test^"'

另一种转义引号的方法(虽然可能不是最好的) ,我发现在某些地方使用的是 使用多个双引号。为了让别人的代码更易读,我会解释的。

下面是一些基本规则:

  1. 当不包装在双引号组中时,空格分隔参数: < br/> program param1 param2 param 3将向 program.exe传递四个参数: < br/> param1param2param3
  2. 双引号组在向程序传递参数时忽略作为值分隔符的空格: < br/> program one two "three and more"将向 program.exe传递三个参数: < br/> onetwothree and more
  3. 现在来解释一下其中的一些困惑:
  4. 与未用双引号包装的文本直接相邻的双引号组连接成一个参数: < br/> hello"to the entire"world充当一个参数: helloto the entireworld
  5. 注意: 前面的规则并不意味着两个双引号组可以直接相邻出现。
  6. 任何双引号 直接跟在结束语之后都被视为(或作为)与双引号组相邻的普通取消包装文本的一部分,但是只有一个双引号: < br/> "Tim says, ""Hi!"""将充当一个参数: Tim says, "Hi!"

因此有三种不同类型的双引号: 打开的双引号、关闭的双引号和充当纯文本的双引号。
下面是最后一句令人困惑的台词:

"   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: "

因此,文本实际上连接了四组字符(其中一组没有任何字符) :
Tim says, 是第一个,包装以逃避空格
"Hi!是第二个,没有包装(没有空格)
是第三个,双引号组不包装任何东西
"是第四个,未包装的结束报价。

可以看到,双引号组不包装任何内容,因为如果没有它,下面的双引号组将打开一个双引号组,而不是充当纯文本。

由此可以看出,内引号和外引号中的三个双引号是纯文本非转义双引号:

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

将按预期打印 Tim said to him, "What's been happening lately?"。因此,三个引号始终可以可靠地用作转义符。然而,在理解它的时候,您可能会注意到,最后的四个引号可以减少到仅仅两个,因为它在技术上是添加另一个不必要的空双引号组。

这里有几个例子来结束这种情况:

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")

最后注意: 我没有从任何教程中读到这些内容-我是通过实验得出这些内容的。因此,我的解释在内部可能是不正确的。尽管如此,上面的所有例子都是按照给出的结果进行评估的,从而验证(但不能证明)我的理论。

我在 Windows 7,64位上仅使用 * 进行了测试。传递参数的 exe 调用(不是 *)。蝙蝠,但我认为它的工作原理是一样的)。

试试这个:

myscript """test"""

参数中的“转义为单个”。

彼得•莫滕森(Peter Mortensen)在回答 Codesmith 问题时引用的第二份文件,让我更加清楚地认识到了这一点。那份文件是 windowsinspired.com 写的。链接重复: 理解 Windows 命令行参数的引用和转义的更好方法

一些进一步的尝试和错误导致以下准则:

用一个插入符号 ^避免每个双引号 "。如果您希望将 Windows 命令 shell 中具有特殊含义的其他字符(例如,<>|&)解释为正则字符,那么也可以使用插入符号来转义它们。

如果希望程序 接收命令行文本 "a\"b c" > d并将其输出重定向到文件 输出,那么从 Windows 命令行 shell 启动程序如下:

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

如果 \"解释为文字双引号,并期望未转义的双引号来分隔包含空格的参数,那么 将命令解释为指定一个参数 a"b c、一个参数 >和一个参数 d

如果 将双引号 ""解释为字面双引号,那么将程序启动为

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

引用文档的关键内容是,对于 Windows 命令 shell,未转义的双引号触发器在两种可能的状态之间切换。

一些进一步的尝试和错误意味着在初始状态下,重定向(到文件或管道)被识别,插入符号 ^转义为双引号,并且从输入中删除插入符号。在另一种状态下,不会识别重定向,插入符号不会转义双引号,也不会移除。让我们将这些状态分别称为“外部”和“内部”。

如果要重定向命令的输出,那么命令 shell 到达重定向时必须处于外部状态,因此在重定向之前必须有偶数个未转义(插入符号)双引号。foo "a\"b " > out.txt不起作用——命令 shell 将整个 "a\"b " > out.txt作为其组合命令行参数传递给 ,而不是仅传递 "a\"b "并将输出重定向到 输出

foo "a\^"b " > out.txt也不会起作用,因为插入符号 ^是在内部状态下遇到的,在这种状态下它是一个普通字符而不是转义字符,所以 "a\^"b " > out.txt被传递给

唯一(希望)始终有效的方法是使命令 shell 始终处于外部状态,因为这样重定向就可以工作了。

如果不需要重定向(或对命令 shell 有特殊意义的其他字符) ,那么可以不使用插入符号。如果 \"解释为文字双引号,那么可以将其调用为

foo "a\"b c"

然后 接收 "a\"b c"作为其组合参数文本,并且可以将其解释为等于 a"b c的单个参数。

现在,最后,回到最初的问题。从 Windows 命令 shell 调用的 myscript '"test"''"test"'传递给 我的剧本。显然,我的剧本将单引号和双引号解释为参数分隔符并删除它们。您需要弄清楚 我的剧本接受哪些字面双引号,然后在命令中指定,使用 ^转义对 Windows 命令 shell 具有特殊意义的任何字符。考虑到在 Unix 上也可以使用 myscript,也许 \"可以做到这一点。试试看

myscript \^"test\^"

或者,如果你不需要重定向,

myscript \"test\"

我从 cmd 调用 powershell,传递引号,这两种转义都不起作用。严重的口音工作,以避免双引号在这个 Win 10表面职业。

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

下面是我为其他字符转义双引号得到的输出:

la\
la^
la
la~

使用另一个引号转义引号会导致没有引号。 正如您所看到的,字符本身被键入,但没有转义为双引号。

也许您来到这里,是因为您想知道如何在传递给 cmd.exe上的 /c的命令中转义所需的引号?但你没有:

CMD /c "MKDIR "foo bar""

将执行

MKDIR "foo bar"

这是我第一眼没有想到的行为。