我知道有类似的问题,但有一件事我找不到答案。 我试图将下面的string传递给batch file:
hello " world
这是一个单一的论点。 这是我的batch file:
@echo off @echo %1
现在,如果我从命令行运行它,我得到以下结果:
>C:\file.bat "hello "" world" "hello "" world" >C:\file.bat "hello \" world" "hello \" >C:\file.bat "hello """ world" "hello """
在所有情况下,我得到了错误的结果,我怎么逃避双引号并正确传递? 或者我应该在batch file本身做任何额外的转换步骤?
作为批处理参数传递字符串字面值hello " world
是不可能的,原因有二:
关于参数标记化,空间不能被转义。 参数始终由未加引号的令牌分隔符分隔,即使它们前面有^
转义字符。 令牌参数令牌分隔符是{space}
, {tab}
;
=
和{0xFF}
。 将令牌分隔符作为参数的一部分的唯一方法是确保分隔符被引用。
引用字符串中的引号是不可能的。 引号是一个状态机:第一个遇到的引用打开引号语义,随后的引用将其关闭。 下一个报价又重新打开,等等。如果报价是关闭的,那么报价字面就可以省略,因为报价已经开始,但是一旦开始报价,就没有办法逃避报价:下一个报价报价总是变成报价。
所以不管你如何添加引号和/或引号,总会有一个不加引号的空格,因此字符串将被视为两个参数。
你可以采用Hapax推荐的策略 – 引用整个字符串,并在字符串"Hello "" world"
双引号。
但是,我会做一个小小的改变,并使用%~1
而不是%1
来删除外部引号。 然后将加倍的引号转换回单引号:
@echo off set "arg1=%~1" set "arg1=%arg1:"=%" echo %arg1%
但是,将字符串文字作为批处理参数传递也存在其他潜在的问题。 最阴险的是双重插入。 如果调用者使用CALL,则不可能将引用的脱字号作为参数传递。 我不会深究这个问题背后的机制。 如果您需要更多信息,请参阅https://stackoverflow.com/a/4095133/1012053 。 但下面说明了这个问题:
test.bat的
@echo %1
– 样本cmd会话 –
D:\test>test "^" "^" D:\test>call test "^" "^^"
由于将字符串文字作为批处理参数传递的许多复杂性,高级批处理脚本中使用的最有效的策略是将该值存储在环境变量中,然后传递变量名称作为参数。 批处理脚本可以使用延迟扩展来获得正确的值:
test2.bat
@echo off setlocal enableDelayedExpansion set "arg1=!%1!" echo !arg1!
– 样本cmd会话 –
D:\test>set "myVar=Hello world! ^&|<>" How are you doing? !^^^&^|^<^>^" D:\test>set myVar myVar=Hello world! ^&|<>" How are you doing? !^&|<> D:\test>test2 myVar Hello world! ^&|<>" How are you doing? !^&|<> D:\test>call test2 myVar Hello world! ^&|<>" How are you doing? !^&|<>
保持报价的方式是把它们加倍。 但是,这通过了他们两人。 然后,您可以处理输入并删除双打。
使用file.bat "hello "" world"
,我们使用:
@echo off set param=%1 set param=%param:""="% echo %param%
(结果: "hello " world"
)
较短的版本:
@echo off set param=%1 echo %param:""="%