Batch file 批量延迟扩展不';不能使用周围的if子句

Batch file 批量延迟扩展不';不能使用周围的if子句,batch-file,scripting,windows-scripting,Batch File,Scripting,Windows Scripting,在下面的脚本中,我使用一个字符串、该字符串的子字符串的最大长度和第三个不存在的变量调用一个子例程以返回子字符串 脚本应检查具有最大子字符串长度的字符串后的下一个字符是否为空格,如果是,则将字符串按该空格剪切(将空格删除为),然后返回子字符串,并通过剪切子字符串部分更改传递的字符串。例如: 字符串:“Hello World Bla” 子字符串长度:5 调用:获取子字符串字符串子字符串长度子字符串 =>字符串:“World Bla”(无空格),子字符串长度:5(无更改),子字符串:“Hello” 这

在下面的脚本中,我使用一个字符串、该字符串的子字符串的最大长度和第三个不存在的变量调用一个子例程以返回子字符串

脚本应检查具有最大子字符串长度的字符串后的下一个字符是否为空格,如果是,则将字符串按该空格剪切(将空格删除为),然后返回子字符串,并通过剪切子字符串部分更改传递的字符串。例如:

字符串:“Hello World Bla”
子字符串长度:5

调用:获取子字符串字符串子字符串长度子字符串

=>字符串:“World Bla”(无空格),子字符串长度:5(无更改),子字符串:“Hello”

这在没有if子句的情况下可以很好地工作,但是当我使用if子句时就不行了,即使我使用了延迟扩展

以下是不带if语句的工作代码:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    SET string=Hello World wasserschutzpolizei
    SET /A substringLength=5
    CALL :get_substring string substringLength substring
    ECHO !string!
    ECHO !substring!
    EXIT /B 0
ENDLOCAL

:get_substring
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET "string=!%~1!"
    SET "substringLength=!%2!"
    SET nextChar=!string:~%substringLength%,1!

    REM IF "!nextChar!"==" " (
        SET substring=!string:~0,%substringLength%!
        ECHO !substring!
        SET /A cutSpaceCount=!substringLength!+1
        SET string=!string:~%cutSpaceCount%!

        ECHO !string!

        ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
    REM ) ELSE (
    REM     Some other case    
    REM )

EXIT /B 0
IF "!nextChar!"==" " (
    SET substring=!string:~0,%substringLength%!
    ECHO !substring!
    SET /A cutSpaceCount=!substringLength!+1
    SET string=!string:~%cutSpaceCount%!

    ECHO !string!

    ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
) ELSE (
    REM Some other case    
)
当我在if语句中注释时,这不起作用:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    SET string=Hello World wasserschutzpolizei
    SET /A substringLength=5
    CALL :get_substring string substringLength substring
    ECHO !string!
    ECHO !substring!
    EXIT /B 0
ENDLOCAL

:get_substring
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET "string=!%~1!"
    SET "substringLength=!%2!"
    SET nextChar=!string:~%substringLength%,1!

    REM IF "!nextChar!"==" " (
        SET substring=!string:~0,%substringLength%!
        ECHO !substring!
        SET /A cutSpaceCount=!substringLength!+1
        SET string=!string:~%cutSpaceCount%!

        ECHO !string!

        ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
    REM ) ELSE (
    REM     Some other case    
    REM )

EXIT /B 0
IF "!nextChar!"==" " (
    SET substring=!string:~0,%substringLength%!
    ECHO !substring!
    SET /A cutSpaceCount=!substringLength!+1
    SET string=!string:~%cutSpaceCount%!

    ECHO !string!

    ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
) ELSE (
    REM Some other case    
)
  • 为什么脚本不能与if语句一起工作
  • 你怎么能修好它

  • 请注意,我的例程还应该包括一个else语句,我删掉了它,因为问题是相同的。

    问题是这行:

    SET string=!string:~%cutSpaceCount%!
    
    如果将此行放置在
    IF
    命令内,则
    cutSpaceCount
    的值将在
    IF
    的代码块(括号)内更改,因此必须通过
    展开该行!cutSpaceCount延迟扩展,而不是通过
    %cutSpaceCount%
    标准扩展

    您应该使用类似于“双延迟扩展”的东西,即类似于此构造:

    SET string=!string:~!cutSpaceCount!!
    
    当然,这不起作用,所以技巧是使用
    for
    命令获取第一次延迟展开的值,然后使用for参数完成第二次延迟展开:

    for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"
    
    当子程序中的最终值返回给调用程序时,也会出现类似的问题。这是最终工作代码:

    @ECHO OFF
    SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
        SET string=Hello World wasserschutzpolizei
        SET /A substringLength=5
        CALL :get_substring string substringLength substring
        ECHO !string!
        ECHO !substring!
        EXIT /B 0
    ENDLOCAL
    
    :get_substring
        SETLOCAL ENABLEDELAYEDEXPANSION
    
        SET "string=!%~1!"
        SET "substringLength=!%2!"
        SET "nextChar=!string:~%substringLength%,1!"
    
        IF "!nextChar!"==" " (
            SET "substring=!string:~0,%substringLength%!"
            ECHO !substring!
            SET /A cutSpaceCount=!substringLength!+1
    
            for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"
    
            ECHO !string!
            for /F "delims=" %%s in ("!string!") do for /F "delims=" %%b in ("!substring!") do (
                ENDLOCAL & SET "%1=%%s" & SET "%3=%%b" & EXIT /B 0
            )
    
        ) ELSE (
            ECHO Some other case    
        )
    
    PS-您不需要在
    SET/A
    命令中展开变量值。而不是:

    SET /A cutSpaceCount=!substringLength!+1
    
    您只需使用:

    SET /A cutSpaceCount=substringLength+1
    

    您似乎对调用延迟扩展时发生的操作序列感到非常困惑

    首先,将
    %var%
    的值替换为
    %var%

    那么!瓦尔!使用结果进行评估

    此操作序列的范围是一条逻辑线,它可以是一条物理线或任意数量的物理线,与终端
    ^
    相连,或者更常见地使用括号中的线序列

    那么在你的主线上,

    CALL :get_substring string substringLength substring
    ECHO !string!
    ECHO !substring!
    ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
    
    由于这些语句不在同一逻辑行中,它们将被单独计算,因此
    !瓦尔=
    %var%

    在子程序(非IF版本)中

    再次是个人陈述。第一个
    set
    将首先替换
    substringlength
    ,然后执行
    set substring=!弦:~0,5作为第二个操作

    每个
    echo
    es都是一个独立的语句,
    可以(最好应该)替换为
    %

    set/a
    语句-嗯,
    set/a
    允许不修饰地使用变量的当前值,因此
    set/a cutSpaceCount=substringLength+1
    set/a cutSpaceCount=%substringLength%+1
    可以在这里使用,而不产生任何逻辑效果

    ENDLOCAL&集%1=%string%&集%3=%substring%&退出/B 0
    将根据上一个代码序列建立的值进行计算

    但是当您添加
    if
    时,代码被括在括号内,因此成为一个逻辑语句,其行为不同

    然后,
    echo
    es需要
    因为要在代码块中显示修改后的值。由于未在代码块的开头设置
    cutSpaceCount
    set string=!字符串:~%cutSpaceCount%将被评估为
    设置字符串=!字符串:~

    然后,
    ENDLOCAL&SET%1=%string%&SET%3=%substring%&EXIT/b0
    将在遇到
    IF
    时,正确替换变量的值

    因此,可能需要一个替换例程

    :获取子字符串
    SETLOCAL ENABLEDELAYEDEXPANSION
    设置“字符串=!%~1!”
    设置“子字符串长度=!%2!”
    设置“子字符串=!字符串:~0,%substringLength%!”
    设置“字符串=!字符串:~%substringLength%”
    如果“%string:~0,1%”==“SET”string=%string:~1%
    ENDLOCAL&集“%1=%string%”和集“%3=%substring%”
    退出/b0
    
    正如其他人已经解释过的,问题在于:

    设置字符串=!字符串:~%cutSpaceCount%!
    
    因为您对在同一逻辑行/代码块中更改的变量
    cutSpaceCount
    使用立即展开(
    %

    一种可能的解决方案是像这样使用
    调用

    callset“string=%%string:~!cutSpaceCount!%%”
    
    call
    引入了另一个变量扩展阶段,因此顺序如下:

  • 立即扩展阶段,其中
    %%
    变为
    %%

    调用集“string=%string:~!cutSpaceCount!%”
    
  • 然后发生延迟扩展(假设样本值为
    5
    ):

    调用集“string=%string:~5%
    
  • 另一个即时扩展阶段由
    调用
    引入,最终获得
    %string:~5%


  • 谢谢你澄清这一点。我真的没有意识到,偏执论中的每件事都被解释为一条逻辑线。给了我非常不同的看法。。。