批处理 - 延迟扩展不适用于周围的if子句

时间:2018-05-28 23:39:17

标签: batch-file scripting windows-scripting

在下面的脚本中,我调用一个带有字符串的子例程,该字符串的子字符串的最大长度以及第三个不存在的变量来获取子字符串。

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

string:" Hello World Bla"
substringLength:5

CALL :get_substring string substringLength substring

=> string:" World Bla" (没有空格),substringLength:5(没有变化),子串:"你好"

没有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语句中发表评论时,这不起作用:

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    
)
  1. 为什么脚本不能使用if语句?
  2. 如何解决?
  3. 请注意我的例行程序还应该包括一个我删除的else语句,因为问题是相同的。

3 个答案:

答案 0 :(得分:4)

问题在于这一行:

SET string=!string:~%cutSpaceCount%!

当此行放在IF命令中时,cutSpaceCount的值在<{1}}的代码块(括号)里面改变,因此必须通过IF延迟扩展来扩展,通过!cutSpaceCount!标准扩展。

你应该使用&#34;双延迟扩展&#34;之类的东西,就像这个结构一样:

%cutSpaceCount%

当然,这不起作用,所以诀窍是使用SET string=!string:~!cutSpaceCount!! 命令来获取第一个延迟扩展的值,然后使用 FOR参数完成第二次延迟扩展:

for

当子例程中的最终值返回到调用程序时,会发生类似的问题。这是最终的工作代码:

for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"

PS - 您不需要在@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 ) 命令中扩展变量值。而不是:

SET /A

你可以简单地使用:

SET /A cutSpaceCount=!substringLength!+1

答案 1 :(得分:3)

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

首先,var的值代替%var%

然后!var!使用结果评估。

此操作序列的范围是一条逻辑行,可能是一条物理行或任何数量的物理行继续终端^或更多通常使用带括号的行序列。

在你的主线上,

CALL :get_substring string substringLength substring
ECHO !string!
ECHO !substring!
ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0

由于这些语句在同一逻辑行中,因此它们将单独评估,因此!var! == { {1}}。

在您的子程序(非IF版本)中,

%var%

再次是个别陈述。第一个 SET substring=!string:~0,%substringLength%! ECHO !substring! SET /A cutSpaceCount=!substringLength!+1 SET string=!string:~%cutSpaceCount%! ECHO !string! 将首先替换set,然后执行substringlength作为第二个操作。

每个SET substring=!string:~0,5! es都是一个独立的声明,echo可能(最好应该)替换为!

%语句 - 好吧,set /a允许变量的当前值使用未修饰,因此set /aSET /A cutSpaceCount=substringLength+1可以在这里使用没有逻辑效果。

SET /A cutSpaceCount=%substringLength%+1将根据前一个代码序列建立的值进行评估。

然而当您添加ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0时,代码会被括起来,因此会成为一个逻辑语句,并采取不同的行为。

if es然后需要 echo,因为您想在代码块已修改的值>。由于!未设置在代码块的开头,因此cutSpaceCount将被评估为SET string=!string:~%cutSpaceCount%!

然后SET string=!string:~!将适当地替换遇到 ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0 时的变量的值

因此,替换例程可能是

IF

答案 2 :(得分:1)

正如其他人已经解释过的那样,问题就在于:

SET string=!string:~%cutSpaceCount%!

因为您对变量%使用立即扩展(cutSpaceCount),该变量在同一逻辑行/代码块中更改。

一种可能的解决方案是使用call,如下所示:

    call set "string=%%string:~!cutSpaceCount!%%"

call引入了另一个变量扩展阶段,因此序列如下:

  1. %%成为%的直接扩展阶段:

    call set "string=%string:~!cutSpaceCount!%"
    
  2. 然后发生延迟扩展(让我们假设样本值为5):

    call set "string=%string:~5%"
    
  3. call引入的另一个即时扩展阶段,最终获得%string:~5%