如何将转义的双引号传递给batch file

我知道有类似的问题,但有一件事我找不到答案。 我试图将下面的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是不可能的,原因有二:

  1. 关于参数标记化,空间不能被转义。 参数始终由未加引号的令牌分隔符分隔,即使它们前面有^转义字符。 令牌参数令牌分隔符是{space}{tab} ; ={0xFF} 。 将令牌分隔符作为参数的一部分的唯一方法是确保分隔符被引用。

  2. 引用字符串中的引号是不可能的。 引号是一个状态机:第一个遇到的引用打开引号语义,随后的引用将其关闭。 下一个报价又重新打开,等等。如果报价是关闭的,那么报价字面就可以省略,因为报价已经开始,但是一旦开始报价,就没有办法逃避报价:下一个报价报价总是变成报价。

所以不管你如何添加引号和/或引号,总会有一个不加引号的空格,因此字符串将被视为两个参数。

你可以采用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:""="%