转义参数中的双引号

Bry*_*eld 94 windows cmd

在Unix中,我可以运行myscript '"test"',我会得到"test".

在Windows中,cmd我得到了'test'.

如何将双引号作为参数传递?我想知道如何从cmd窗口手动执行此操作,因此我不必编写程序来测试我的程序.

Cod*_*ith 183

另一种逃避引用的方法(尽管可能不是更好),我发现在某些地方使用的使用多个双引号.为了使其他人的代码清晰,我将解释.

这是一套基本规则:

  1. 如果不是用双引号组,空格分隔参数:
    program param1 param2 param 3将通过四个参数program.exe:
         param1,param2,param,和3.
  2. 双引号组忽略空格作为参数传递给程序时价值分离:
    program one two "three and more"将通过三个参数program.exe:
         one,twothree and more.
  3. 现在来解释一些困惑:
  4. 直接与未使用双引号括起的文本相邻的双引号组合并为一个参数:
    hello"to the entire"world作为一个参数:helloto the entireworld.
  5. 注意:之前的规则并不意味着两个双引号组可以直接相邻.
  6. 直接在结束引用之后的任何双引号被视为与双引号组相邻的普通未包装文本(或作为其一部分),但只有一个双引号:
    "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!是第二个,没有包裹(没有空格)
 is the third, a double-quote group wrapping nothing
"是第四个,未打开的近距离报价.

正如你所看到的,双引号组不包含任何东西仍然是必要的,因为如果没有它,下面的双引号会打开一个双引号组,而不是作为纯文本.

因此,应该认识到,因此,在内部和外部引号中,三个双引号充当纯文本未转义的双引号:

"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,64bit上测试了这个,只使用带参数传递的*.exe调用(不是*.bat,但我认为它的工作方式相同).

  • ...我只能说,Windows批处理文件有问题.为了基督的缘故,这是*逃避引号*; 它不应该是某种火箭科学. (44认同)
  • +1,但请注意,此行为取决于应用程序.在Windows中,每个应用程序都会解析自己的命令行参数.我相信你所描述的行为是微软的标准C库,我认为它也被大多数其他Windows C编译器复制. (11认同)
  • 有关详细说明,请参阅*[如何解析命令行参数](http://daviddeley.com/autohotkey/parameters/parameters.htm)*和*[更好地了解Windows命令行的引用和转义参数](http://www.windowsinspired.com/understanding-the-command-line-string-and-arguments-received-by-a-windows-program/)*. (8认同)
  • @JamesKo我完全同意.Windows命令行的神秘荒谬和不一致永远不会让我感到愤怒.谁设计了这个垃圾?哦,多年来浪费的时间!Unix非常简单,相比之下更有意义. (4认同)
  • 你最后一次出现多次错误.程序"""ab""" - >("ab"),程序"你好"""引号"" - >(问到"引号",程序""""你好世界"" - >("你好") (世界),节目"""你好"世界"" - >("你好"(世界),节目"""你好"世界"" - >("你好世界"),节目"你好"""世界"" - >(你好"世界") (2认同)

smw*_*dia 23

试试这个:

myscript """test"""
Run Code Online (Sandbox Code Playgroud)

""在参数中"转义为单个".

  • 这并不完全正确。试试 `myscript """test test"""` 还是不行(第一个参数是作为 `"test` 传递的。实际上,你需要三个引号: `myscript """"test test""` 第三个不过,可以跳过末尾的引用。 (3认同)
  • 也许没有发现这个问题,但是当我需要将`char**argv`从我的C启动器传递给另一个使用`spawn`或`exec`等函数的进程时,这有助于我.谢谢.:-) (2认同)

mou*_*sio 19

我无法快速重现这些症状:如果我尝试myscript '"test"'使用myscript.bat包含just @echo.%1或者甚至的批处理文件@echo.%~1,我会得到所有引号:'"test"'

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

  • Windows:通过调用可执行文件而不是shell执行globbing,shell扩展和参数unescaping的操作系统.您永远不知道调用的可执行文件遵循哪种约定(如果有). (24认同)
  • 有价值的输入:https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/.插入符确实是`cmd`的首选符号. (6认同)
  • 那么也许[这个问题]的答案(http://stackoverflow.com/q/4192376/653295)可能会对你有所帮助吗? (3认同)
  • 实际上^对我来说不起作用,但是根据这个答案,我做了:http://stackoverflow.com/questions/2403647/how-to-escape-parameter-in-windows-command-line (3认同)
  • 哈!我从来没有想到这是'wscript`的错!把它留给Windows :) (2认同)

Lou*_*ous 12

Peter Mortensen 在对 Codesmith 的答案的评论中引用的第二份文件让我的情况变得更加清晰。该文档由 windowsinspired.com 编写。重复链接:理解 Windows 命令行参数的引用和转义的更好方法

一些进一步的尝试和错误导致了以下指导方针:

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

如果您希望程序foo接收命令行文本"a\"b c" > d并将其输出重定向到文件out.txt,则从 Windows 命令 shell 启动您的程序,如下所示:

foo ^"a\^"b c^" ^> d > out.txt
Run Code Online (Sandbox Code Playgroud)

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

相反,如果foo将双双引号解释""为文字双引号,则将程序启动为

foo ^"a^"^"b c^" ^> d > out.txt
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

foo "a\"b c"
Run Code Online (Sandbox Code Playgroud)

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

现在——最后——回到最初的问题。 myscript '"test"'从 Windows 命令 shell 调用会传递'"test"'myscript。显然myscript将单引号和双引号解释为参数分隔符并将其删除。您需要弄清楚myscript接受什么作为文字双引号,然后在命令中指定它,用于^转义对 Windows 命令 shell 具有特殊含义的任何字符。鉴于这myscript在 Unix 上也可用,也许\"可以解决问题。尝试

myscript \^"test\^"
Run Code Online (Sandbox Code Playgroud)

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

myscript \"test\"
Run Code Online (Sandbox Code Playgroud)