批处理文件在FOR循环中使用特殊字符和引号修改字符串

时间:2017-02-16 03:25:35

标签: windows batch-file cmd

下面的代码片段会删除所有额外的垃圾,直到错误生成代码,

  

)“”此时出人意料。

@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!
)

基本上,在真实的脚本中,我正在尝试调用一个命令行工具,该工具采用一个带有可能特殊字符的复杂字符串,以及一个正则表达式。

我想出了一个解决方法,即在^的最后一句话之前添加一个插入符号%%I):

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

但这感觉就像是黑客。我做错了什么,如果没有肮脏的黑客行为,我该怎么做才能获得理想的行为?

2 个答案:

答案 0 :(得分:2)

无需黑客即可解决问题:

  • 确保!字符。在您的regex变量值中,系统会将其识别为文字

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

    • 由于setlocal enabledelayedexpansion文字 !字符。内部"..."必须转发为^!

    • 请注意,<name>=<value>令牌是双引号整体,以防止对该值进行额外解释。

  • regex循环体内的参考变量for 延迟

    • 使用!regex!代替%regex%

    • 为了使得到的命令行更加健壮 - 即使在这种特定情况下不需要 - 确保regex的值用双引号括起来(注意%%I - as仅仅是一个数字 - 需要引用):
      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))"

至于你做错了什么

%<name>% - 样式变量引用 - 除了循环变量(在本例中为%%I) - 在循环体((...))内扩展循环甚至是解析,因此这些变量引用的可以打破循环。

以下是演示此问题的最小示例

@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!
)

答案 1 :(得分:2)

@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不会产生正确的结果。然而,在for内,每对插入符被解释为单个插入符号,因此所需的转义符是预期输出所需的,大概是call crv.exe "5" "(Test_Health=(?!100))"之类......等等。