Batch file 批量延迟扩展不';不能使用周围的if子句
在下面的脚本中,我使用一个字符串、该字符串的子字符串的最大长度和第三个不存在的变量调用一个子例程以返回子字符串 脚本应检查具有最大子字符串长度的字符串后的下一个字符是否为空格,如果是,则将字符串按该空格剪切(将空格删除为),然后返回子字符串,并通过剪切子字符串部分更改传递的字符串。例如: 字符串:“Hello World Bla”Batch file 批量延迟扩展不';不能使用周围的if子句,batch-file,scripting,windows-scripting,Batch File,Scripting,Windows Scripting,在下面的脚本中,我使用一个字符串、该字符串的子字符串的最大长度和第三个不存在的变量调用一个子例程以返回子字符串 脚本应检查具有最大子字符串长度的字符串后的下一个字符是否为空格,如果是,则将字符串按该空格剪切(将空格删除为),然后返回子字符串,并通过剪切子字符串部分更改传递的字符串。例如: 字符串:“Hello World Bla” 子字符串长度:5 调用:获取子字符串字符串子字符串长度子字符串 =>字符串:“World Bla”(无空格),子字符串长度:5(无更改),子字符串:“Hello” 这
子字符串长度: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
)
请注意,我的例程还应该包括一个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%
谢谢你澄清这一点。我真的没有意识到,偏执论中的每件事都被解释为一条逻辑线。给了我非常不同的看法。。。