下面的这个代码片断被剥离了所有额外的垃圾,直到错误生成的代码,
)“”在这个时候是意外的。
@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>
标记作为一个整体被双引号,以防止额外解释值。
引用变量regex
在for
循环体内延迟 :
使用!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))"
等…