在批处理脚本中转义双引号

时间:2009-02-18 17:19:39

标签: scripting parameters batch-file escaping quotes

如何使用转义双引号替换批处理文件参数中的所有双引号?这是我当前的批处理文件,它扩展了字符串中的所有命令行参数:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

然后使用该字符串调用Cygwin的bash,执行Linux交叉编译器。不幸的是,我正在将这些参数传递到我的批处理文件中:

"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions 
-Wno-inline -Wall  -DNDEBUG   -c 
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o" 
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"

传入的第一个路径的第一个引号过早地结束了传递给GCC的字符串,并将其余参数直接传递给bash(这非常失败。)

我想如果我可以将参数连接成单个字符串然后转义它应该正常工作的引号,但我很难确定如何执行此操作。有谁知道吗?

5 个答案:

答案 0 :(得分:91)

批处理脚本中的转义字符为^。但对于双引号字符串,请将引号加倍:

"string with an embedded "" character"

答案 1 :(得分:22)

谷歌最终想出了答案。批处理中字符串替换的语法是:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

产生“复制我”。我的脚本现在看起来像这样:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

将[{1}}的所有实例替换为",并为bash正确转义。

答案 2 :(得分:8)

作为mklement0's excellent answer的补充:

几乎所有可执行文件都接受\"作为转义"。但是,使用DELAYEDEXPANSION几乎只能在cmd中安全使用 要明确地将文字"发送到某个进程,请将\"分配给环境变量,然后在需要传递引号时使用该变量。例如:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

注意SETLOCAL ENABLEDELAYEDEXPANSION似乎只在批处理文件中有效。要在交互式会话中获取DELAYEDEXPANSION,请启动cmd /V:ON

如果您的批处理文件不能与DELAYEDEXPANSION一起使用,您可以暂时启用它:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

如果您想要从包含以""转义的引号的变量传递动态内容,则可以在展开时将""替换为\"

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

%...%样式扩展,这种替换不安全!

如果OP bash -c "g++-linux-4.1 !v_params:"=\"!"是安全版本。

如果出于某种原因即使暂时无法启用DELAYEDEXPANSION,请继续阅读:

如果总是需要转义特殊字符,而不仅仅是有时候,那么在cmd中使用\"会更安全一些。 (忘记插入符号的可能性较小,如果它一致......)

为了达到这个目的,我们可以在任何带有插入符号(^")的引号之前,引号应该到达子进程,因为文字必须另外使用强制转义(\^")进行转义。 所有 shell元字符也必须使用^转义,例如& => ^&; | => ^|; > => ^>;等

示例:

child ^"malicious argument\^"^&whoami^"

来源:Everyone quotes command line arguments the wrong way,请参阅“更好的引用方法”

要传递动态内容,需要确保以下内容:
包含变量的命令部分必须被cmd.exe视为“引用”(如果变量可以包含引号,则这是不可能的 - 不写%var:""=\"% )。为实现此目的,变量之前的最后"和变量之后的第一个"不是^ - 已转义。这两个"之间的cmd-metacharacters不得转义。示例:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

如果%dynamic_content%可以包含不匹配的引号,则表示不安全。

答案 3 :(得分:0)

如果字符串已包含在引号中,则使用另一个引号将其操作无效。

echo "Insert tablename(col1) Values('""val1""')" 

答案 4 :(得分:-2)

例如从批处理文件运行的虚幻引擎自动化工具-这对我有用

例如:  -cmdline =“ -Messaging” -device = device -addcmdline =“-SessionId = session -SessionOwner ='owner'-SessionName ='Build'-dataProviderMode = local -LogCmds ='LogCommodity OFF'-execcmds ='自动化列表;运行测试tests + separated + by + T1 + T2;退出“ -run

希望这对某人有帮助,为我工作。