繁体   English   中英

转义参数中的双引号

[英]Escape double quotes in parameter

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

在 Windows cmd我得到'test'

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

我发现在某些地方使用的另一种转义引号的方法(尽管可能不是可取的)是使用多个双引号 为了让其他人的代码清晰易读,我会解释一下。

这是一组基本规则:

  1. 当不包含在双引号组中时,空格分隔参数:
    program param1 param2 param 3将传递四个参数给program.exe
    param1param2param3
  2. 将参数传递给程序时,双引号组会忽略空格作为值分隔符:
    program one two "three and more"将传递三个参数给program.exe
    onetwothree 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!是第二个,没有包裹(没有空格)
是第三个,一个不包含任何内容的双引号组
"是第四个,展开的结束引号。

正如您所看到的,双引号组仍然需要什么都不包裹,因为如果没有它,下面的双引号将打开一个双引号组,而不是充当纯文本。

由此,应该可以看出,因此,内外引号,三个双引号充当纯文本未转义双引号:

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

最后说明:我没有从任何教程中阅读任何内容 - 我通过实验想出了所有内容。 因此,我的解释在内部可能并不正确。 尽管如此,上面的所有示例都按照给定的方式进行评估,从而验证(但不是证明)我的理论。

我仅使用带有参数传递的 *.exe 调用(不是 *.bat,但我认为它的工作原理相同)在 64 位 Windows 7 上对此进行了测试。

尝试这个:

myscript """test"""

"" 转义到参数中的单个 "。

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

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

Peter Mortensen 在他对 Codesmith 回答的评论中引用的第二份文件让我更清楚地了解情况。 该文档由 windowsinspired.com 编写。 链接重复: 一个更好的方法来理解 Windows 命令行参数的引用和转义

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

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

如果您希望您的程序foo接收命令行文本"a\\"bc" > d并将其输出重定向到文件out.txt ,请按如下方式从 Windows 命令外壳启动您的程序:

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

如果foo\\"解释为字面双引号并期望未转义的双引号分隔包含空格的参数,则foo会将命令解释为指定一个参数a"bc 、一个参数>和一个参数d

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

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

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

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

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

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

(希望)始终有效的唯一方法是将命令外壳始终保持在外部状态,因为这样重定向就起作用了。

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

foo "a\"b c"

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

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

myscript \^"test\^"

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

myscript \"test\"

我正在从 cmd 调用 powershell,并传递引号,这里没有任何转义。 在这个 Win 10 Surface Pro 上,重音可以避免双引号。

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

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

la\
la^
la
la~

使用另一个引号来转义引号导致没有引号。 如您所见,字符本身被输入,但没有转义双引号。

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

在Windows cmd我得到'test'

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

也许您来到这里,因为您想知道如何在传递给/c on cmd.exe的命令中转义所需的引号? 好吧,您不会:

CMD /c "MKDIR "foo bar""

将执行

MKDIR "foo bar"

这确实是我第一眼没想到的行为。 一目了然的不一致。

暂无
暂无

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

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