批处理 - 设置/重置参数调用子程序带有感叹号(!)和延迟扩展?

时间:2018-06-03 19:54:13

标签: batch-file cmd scripting windows-scripting

我有两个使用延迟扩展的本地人。 1. Local调用子程序,该子程序包括2. Local,它定义2个变量并使用FOR /F ...将它们的值设置为参数值。只要字符串不包含一个或多个感叹号,这就可以正常工作。以下工作脚本显示了该问题:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

    CALL :get_substrings testString substr
    ECHO Inside 1. local:
    ECHO !testString!
    ECHO !substr!

    EXIT /B 0
ENDLOCAL


:get_substrings
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET string="World^! wasserschutzpolizei^!"
    SET substring="Hello^!"
    ECHO Inside get_substrings:
    ECHO !string!
    ECHO !substring!

    FOR /F "delims=" %%s IN ("!string!") DO FOR /F "delims=" %%b IN ("!substring!") DO (
        ENDLOCAL & SET "%1=%%s" & SET "%2=%%b" & EXIT /B 0
    )
EXIT /B 0

输出:

Inside get_substrings:
"World! wasserschutzpolizei!"
"Hello!"
Inside 1. local:
"World"
"Hello"

预期:

Inside get_substrings:
"World! wasserschutzpolizei!"
"Hello!"
Inside 1. local:
"World! wasserschutzpolizei!"
"Hello!"

如果删除stringsubstring中的感叹号,脚本将按预期工作。

因为这只是一个例子考虑......

  1. 不使用延迟扩展不是一种选择,而且......
  2. 使用一个本地是不可取的。
  3. 当然,如果真的需要一件甚至两件事,而且我没有其他方法可以接受指出的其他答案。

    因此...

    1. 如何在预期部分中显示的1. local中获取带感叹号的值?
    2. 为什么它不适用于设置参数值的当前方式?
    3. 感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

您可以选择在调用子例程时禁用延迟扩展:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION

    CALL :get_substrings testString substr
    SETLOCAL ENABLEDELAYEDEXPANSION
    ECHO Inside 1. local:
    ECHO !testString!
    ECHO !substr!
    ENDLOCAL

    EXIT /B 0
ENDLOCAL


:get_substrings
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET string="World^! wasserschutzpolizei^!"
    SET substring="Hello^!"
    ECHO Inside get_substrings:
    ECHO !string!
    ECHO !substring!

    FOR /F "delims=" %%s IN ("!string!") DO FOR /F "delims=" %%b IN ("!substring!") DO (
        ENDLOCAL & SET "%1=%%s" & SET "%2=%%b" & EXIT /B 0
    )
EXIT /B 0

这样可以避免在启用延迟扩展时展开for变量%%s%%b,因为这是最后一步,因此感叹号已被消耗。

答案 1 :(得分:2)

将:get_substrings函数的返回部分更改为:

...
set "return1=!string:"=""!"
set "return1=%return1:!=^^^!%"
set "return1=!return1:""="!"

set "return2=!substring:"=""!"
set "return2=%return2:!=^^^!%"
set "return2=!return2:""="!"

FOR /F "delims=" %%s IN ("!return1!") DO FOR /F "delims=" %%b IN ("!return2!") DO (
    ENDLOCAL & SET "%1=%%s" & SET "%2=%%b" & EXIT /B 0
)

但为什么你的解决方案失败了呢? 问题是set "%1=%%s"在延迟扩展上下文中执行,因为您的完整批次使用延迟扩展 但延迟扩展是批量解析器的最后一个扩展阶段,它是在%%s的参数扩展之后。 因此,解析器会尝试扩展感叹号,当只有一个感叹号会被删除时,如果"World! wasserschutzpolizei!"中有两个感知标记,它会将变量! wasserschutzpolizei!扩展为它的值(在此处)情况似乎是空的)。

解决方案只是在任何感叹号前放置插入符号 但是你在样本中也使用了引号,这使得更复杂的东西更多 为了避免引号和插入符号出现问题,可以轻松地将所有引号加倍,添加插入符号并将双引号更改回单引号。

相关问题