参数中的转义双引号


109

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

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

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


2
自接触Windows机器已有好几年了,但是标准的转义字符(反斜杠\)不起作用吗?例如myscript \"test\"
Gazler 2011年

不。我得到\ test \。我怀疑这是因为Windows使用\而不是/,所以反斜杠不能用作转义符。但是我真的不知道。
布赖恩·菲尔德

Idk使用的是哪个版本的Windows,但是\“在Windows 7(最终版本)上可以正常工作。虽然还有另一种方法可以处理多个引号(即“””变成“或其他形式”),但我不能弄清楚何时以及它是如何工作。
CodeSmith的

Answers:


22

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

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


3
那么,也许这个问题的答案可能会进一步帮助您?
mousio

2
哈!我从来没有想过这是wscript错的!留给Windows :)
Bryan Field

4
其实^没有为我工作,但\做到了,每个这样的回答:stackoverflow.com/questions/2403647/...
kalenjordan

26
Windows:操作系统,在其中通过调用可执行文件而不是Shell来执行globbing,shell扩展和参数转义。您永远都不知道所调用的可执行文件遵循哪种约定(如果有)。
2014年

7
宝贵的意见:blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/…。插入符号确实是选择的逃生字符cmd
彼得-恢复莫妮卡

198

我发现在某些地方使用的另一种转义引号(虽然可能不是首选)是使用多个双引号。为了使其他人的代码清晰易懂,我将进行解释。

这是一组基本规则:

  1. 如果不是用双引号组,空格分隔参数:
    program param1 param2 param 3将通过四个参数program.exe
         param1param2param,和3
  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!"

因此,存在三种不同类型的双引号:打开的引号,关闭的引号和充当纯文本的引号。
这是最后一条令人困惑的行的细目:

“打开双引号组
内的T
我在里面
在“ s”内
    内的-空间不会分开
在“”内
里面的一个
在“”内的y
在“”内
,在“”内
    内的-空间不会分开
“封闭双引号组
“引号紧随其后-用作普通的未包装文本:”
以外的H-加入先前的相邻群组
我在外面--
!外面的“”-...
“打开双引号组
“封闭双引号组
“引号紧随其后-用作普通的未包装文本:”

因此,文本有效地连接了四个字符组(但是,一个字符什么都没有):
Tim says,  是第一个字符,被包装以转义空格以逃避
"Hi!是第二个,没有包装的字符(没有空格)
 是第三个,双引号组则不包含任何字符
"是第四个,展开后的收盘价。

如您所见,不包含任何内容的双引号组仍然是必需的,因为没有它,下面的双引号将打开一个双引号组,而不是充当纯文本。

由此可见,在内部和外部引号中,三个双引号充当纯文本未转义的双引号:

“蒂姆对他说,”“”最近发生了什么事?”

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

下面是一些关闭它的示例:

程序ab REM发送(a)和(b)
程序“”“ a”“” REM发送(“ a”)
程序“”“ a b”“” REM发送(“ a)和(b”)
程序“”“”你好,“”“迈克说。” REM发送(“您好,”迈克说。)
程序“” a“” b“” c“” d“” REM发送(abcd),因为“”组不包裹任何内容
REM发送的程序“ hello to“”“ quotes”“(您好,” quotes“)
程序“”“” hello world“” REM发送(“ hello world”)
程序“”“”你好“世界”“ REM发送(”你好世界“)
程序“”“”你好“世界”“ REM发送(”你好)和(世界“)
程序“ hello“” world“”“ REM发送(hello” world“)
程序“ hello”“” world“” REM发送(hello“ world”)

最后的注意事项:我没有从任何教程中阅读任何内容-我通过实验提出了所有这些内容。因此,我的解释在内部可能并不正确。但是,以上所有示例均按给定值进行了评估,从而验证了(但未证明)我的理论。

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


11
+1,但请注意,此行为取决于应用程序。在Windows中,每个应用程序都会解析其自己的命令行参数。我相信您所描述的行为是微软标准C库的行为,我认为大多数其他Windows C编译器也会复制该行为。
哈里·约翰斯顿

3
您的上一个脚本中有多个错误。程序““” ab“”“->(” ab“),程序” hello to“”“ quotes”“->(hello to” quotes),程序“”“” hello world“”->(“ Hello) (world),程序“”“” hello“ world”“->(” hello)(world),程序“”“” hello“ world”“->(” hello world),程序“ hello”“” world“”- >(您好,“世界”)
汤姆森

46
...我只能说Windows批处理文件有问题。为了基督的缘故,这是引号。它不必一定是某种火箭科学。
James Ko

4
@JamesKo我完全同意。Windows命令行的奥秘荒谬和不一致永远不会激怒我。谁设计了这个垃圾?哦,多年来浪费了时间!Unix非常简单,相比之下意义非凡。
卡洛斯·伊瓦拉


24

试试这个:

myscript """test"""

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


1
那不是很正确。尝试myscript """test test""",它不起作用(第一个参数作为传递"test。Acutally,您需要使用三个引号:myscript """"test test""但是,可以跳过结尾的第三个引号。–
Ignitor

如果我需要在此处删除所有引号并将参数值放在选择查询过滤器中使用的字符串中怎么办?有人可以帮忙吗?
SFDC_Learner

2
也许对这个问题没有发现,但是当我需要char **argv使用诸如spawn或函数从C启动器传递到另一个进程时,这对我有所帮助exec。谢谢。:-)
virgo47

2

彼得·莫滕森(Peter Mortensen)在他对Codesmith的回答的评论中引用的第二份文件对我来说更清楚了。该文档由windowsinspired.com编写。重复了该链接:了解Windows命令行参数的引用和转义的更好方法

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

"用尖号转义每个双引号^。如果你想其他字符有特殊意义的Windows命令外壳(例如<>|&)被解释为常规字符代替,然后用尖逃避他们。

如果要让程序foo接收命令行文本"a\"b c" > d并将其输出重定向到文件out.txt,则可以从Windows命令外壳按如下所示启动程序:

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

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

相反,如果foo将双引号双引号解释""为文字双引号,则以

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

引用文件的主要见解是,对于Windows命令外壳,未经转义的双引号会触发两个可能状态之间的切换。

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

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

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

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

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

foo "a\"b c"

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

现在-最后-原来的问题。 myscript '"test"'从Windows命令shell调用传递'"test"'myscript。显然,myscript将单引号和双引号解释为参数定界符并将其删除。您需要找出myscript作为文字双引号接受的内容,然后在命令中进行指定,^以转义Windows命令外壳中所有具有特殊含义的字符。鉴于myscript在Unix上也可以使用,也许\"就可以了。尝试

myscript \^"test\^"

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

myscript \"test\"

谢谢!我在墙上敲打头,试图运行vbscript,将cmd提示文本回显到cmd提示文本中-我继承了这一点-无法找到一种避免引号的方法。
PopeDarren

0

我从cmd调用powershell,并传递引号,但这里的两个转义符均无效。重音使这个Win 10 Surface Pro避免了双引号。

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

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

la\
la^
la
la~

使用另一个引号将引号转义会导致没有引号。如您所见,字符本身已键入,但没有转义双引号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.