代码之家  ›  专栏  ›  技术社区  ›  goulashsoup

批量设置/重置参数调用带有感叹号(!)的子例程延迟扩张?

  •  3
  • goulashsoup  · 技术社区  · 7 年前

    我有两个本地人在使用延迟扩展。一号。本地调用包含2的子例程。定义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!"
    

    如果删除中的感叹号 string substring 脚本按预期工作。

    因为这只是一个例子考虑一下…

    1. 不使用延迟扩展不是一个选项,而且…
    2. 使用一个本地是不可取的。

    当然,如果这两件事中的一件或两件都是必须的,而且我没有其他办法接受其他指出这一点的答案。

    所以…

    1. 如何获取1中带有感叹号的值。本地的就像我在 预期 部分?
    2. 为什么它不能以当前的方式设置参数值?

    谢谢你的帮助!

    2 回复  |  直到 7 年前
        1
  •  2
  •   jeb    7 年前

    将: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! 它的价值(在你的情况下,它似乎是空的)。

    该解决方案只需在任何感叹号前面加上插入符号。
    但你也在你的例子中使用引号,这会使更多的事情变得更复杂。
    为了避免引号和插入符号出现问题,很容易将所有引号加倍,添加插入符号并将加倍的引号改回单引号。

        2
  •  3
  •   aschipfl    7 年前

    调用子例程时,是否可以禁用延迟扩展:

    @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 启用延迟扩展时,因为这是最后一步,所以感叹号被使用。