首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >批量延迟扩展不适用于周围的if子句

批量延迟扩展不适用于周围的if子句
EN

Stack Overflow用户
提问于 2018-05-29 07:39:17
回答 3查看 122关注 0票数 2

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

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

字符串:"Hello World Bla“

substringLength: 5

CALL :get_substring string substringLength substring

=>字符串:"World Bla“(无空格),substringLength: 5(无变化),子串:"Hello”

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

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

代码语言:javascript
复制
@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语句中进行注释时,这不起作用:

代码语言:javascript
复制
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-statement?

  • How可以修复该脚本吗?
  1. 为什么脚本不起作用?

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-29 09:13:48

问题是这一行:

代码语言:javascript
复制
SET string=!string:~%cutSpaceCount%!

当该行放在IF命令中时,cutSpaceCount的值将在IF的代码块(圆括号)中更改,因此必须通过!cutSpaceCount!延迟扩展而不是通过%cutSpaceCount%标准扩展来扩展它。

您应该使用类似于"double delayed“的东西,即类似于下面的结构:

代码语言:javascript
复制
SET string=!string:~!cutSpaceCount!!

当然,这不起作用,所以诀窍是使用for命令获取第一个延迟扩展的值,然后使用FOR参数完成第二个延迟扩展:

代码语言:javascript
复制
for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"

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

代码语言:javascript
复制
@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命令中展开变量值。而不是:

代码语言:javascript
复制
SET /A cutSpaceCount=!substringLength!+1

您可以简单地使用:

代码语言:javascript
复制
SET /A cutSpaceCount=substringLength+1
票数 4
EN

Stack Overflow用户

发布于 2018-05-29 09:31:33

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

首先,用%var%替换var的值。

然后!使用结果进行评估。

该操作序列的范围是一条逻辑线路,其可以是一条物理线路或用终端^或更常见地使用带括号的线路序列继续的任意数量的物理线路。

然后在你的主线中,

代码语言:javascript
复制
CALL :get_substring string substringLength substring
ECHO !string!
ECHO !substring!
ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0

由于这些语句不在同一逻辑行中,因此将分别计算它们,因此!var!==%var%

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

代码语言:javascript
复制
    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!作为第二个操作执行。

每个echoes都是一个独立的语句,并且!可以(最好应该)被%取代。

set /a语句--好吧,set /a允许不加修饰地使用变量的当前值,因此在这里使用SET /A cutSpaceCount=substringLength+1SET /A cutSpaceCount=%substringLength%+1不会产生任何逻辑效果。

ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0将根据先前代码序列建立的值进行评估。

然而,当您添加if时,代码是用括号括起来的,因此会变成一条逻辑语句,并以不同的方式运行。

然后,echoes需要!,因为您希望在代码块中显示修改后的值。由于在代码块的开头未设置cutSpaceCount,因此SET string=!string:~%cutSpaceCount%!将被计算为SET string=!string:~!

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

因此,替换例程可能是

代码语言:javascript
复制
:get_substring
SETLOCAL ENABLEDELAYEDEXPANSION

SET "string=!%~1!"
SET "substringLength=!%2!"
SET "substring=!string:~0,%substringLength%!"
SET "string=!string:~%substringLength%!"
IF "%string:~0,1%"==" " SET "string=%string:~1%"
ENDLOCAL & SET "%1=%string%" & SET "%3=%substring%"
EXIT /B 0
票数 3
EN

Stack Overflow用户

发布于 2018-05-29 17:58:33

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

代码语言:javascript
复制
SET string=!string:~%cutSpaceCount%!

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

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

代码语言:javascript
复制
    call set "string=%%string:~!cutSpaceCount!%%"

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

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

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

  • then延迟扩容(假设取样值为5):

call引入call set "string=%string:~5%"

  • another立即扩展阶段,最终得到%string:~5%.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50574549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档