batch file在FOR循环中使用特殊的字符和引号来处理string

下面的这个代码片断被剥离了所有额外的垃圾,直到错误生成的代码,

)“”在这个时候是意外的。

@echo off SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS Set "regex="(Test_Health=(?!100))"" echo Regex is: %regex% FOR /L %%I IN (1,1,5) DO ( Set "to_call=call crv.exe "%%I" %regex%" echo About to call: !to_call! ) 

基本上,在真正的脚本中,我试图调用一个命令行工具,它接受一个复杂的string,其中可能包含特殊的字符以及正则expression式。

我想出了一个解决方法,即在%%I之前添加一个脱字号( ^ )。

 Set "to_call=call crv.exe "%%I^" %regex%" 

但是,这感觉像一个肮脏的黑客。 我做错了什么,我该怎么做才能得到所需的行为没有肮脏的黑客?

要解决您的问题,而不是黑客:

  • 确保! 焦炭。 在你的regex变量值被识别为一个文字

    • Set "regex=(Test_Health=(?^!100))"

    • 由于setlocal enabledelayedexpansion字面 ! 字符。 里面"..."必须作为^!逃脱^!

    • 请注意, <name>=<value>标记作为一个整体被双引号,以防止额外解释值。

  • 引用变量regexfor循环体内延迟

    • 使用!regex! 而不是%regex%

    • 为了使得到的命令行更加健壮 – 即使在这种特殊情况下不需要 – 确保regex的值用双引号引起来(注意%%I – 仅仅是一个数字 – 不需要引用):
      Set "to_call=call crv.exe %%I "!regex!""

把它放在一起:

 @echo off setlocal enabledelayedexpansion enableextensions Set "regex=(Test_Health=(?^!100))" echo Regex is: %regex% FOR /L %%I IN (1,1,5) DO ( Set "to_call=call crv.exe %%I "!regex!"" echo About to call: !to_call! ) 

收益率:

 Regex is: (Test_Health=(?100)) call crv.exe 1 "(Test_Health=(?!100))" call crv.exe 2 "(Test_Health=(?!100))" call crv.exe 3 "(Test_Health=(?!100))" call crv.exe 4 "(Test_Health=(?!100))" call crv.exe 5 "(Test_Health=(?!100))" 

至于你做错什么

除了循环变量(本例中为%%I )之外, %<name>%风格的变量引用在循环体内( (...) )被展开,所以这个变量的引用可以打破循环。

这是一个最小的例子 ,演示了这个问题:

 @echo off Set "regex=))" FOR %%I IN ("dummy") DO ( rem !! breaks, because the up-front %regex% expansion causes a syntax error. echo %regex% ) 

延迟扩展 – 通过在变量名中加入!...! ,假设setlocal enabledelayedexpansion有效 – 绕过这个问题:

 @echo off setlocal enabledelayedexpansion Set "regex=))" FOR %%I IN ("dummy") DO ( rem OK - outputs "))" echo !regex! ) 
 @ECHO OFF SETLOCAL Set "regex="(Test_Health=(?^^^^!100^^)^^)"" SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS echo Regex is: %regex% FOR /L %%I IN (1,1,5) DO ( Set "to_call=call crv.exe "%%I" %regex%" echo About to call: !to_call! ) GOTO :EOF 

排序取决于你的“期望的行为”是什么。 不幸的是,你没有指定。

这是理解cmd是如何工作的 – 通过替换,使用转义字符和发生的顺序。

报告正则表达式的echo不会产生正确的结果。 然而,在这里面,每一对脱字符都被理解为一个脱字符号,所以所需的转义符号就像预期的输出所要求的那样,大概call crv.exe "5" "(Test_Health=(?!100))"等…