在下面的脚本中,我调用了一个子例程,其中包含一个字符串、该字符串的子字符串的最大长度和第三个不存在的变量,以取回子字符串。
脚本应该检查具有最大子串长度的字符串之后的下一个字符是否为空格,如果是,则按该空格剪切该字符串(删除空格)并返回子字符串,并通过剪切子字符串部分来更改传递的字符串。示例:
字符串:"Hello World Bla“
substringLength: 5
CALL :get_substring string substringLength substring
=>字符串:"World Bla“(无空格),substringLength: 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语句中进行注释时,这不起作用:
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?
请注意,我的例程还应该包含一个else语句,因为问题是相同的,所以我去掉了它。
发布于 2018-05-29 09:13:48
问题是这一行:
SET string=!string:~%cutSpaceCount%!
当该行放在IF
命令中时,cutSpaceCount
的值将在IF
的代码块(圆括号)中更改,因此必须通过!cutSpaceCount!
延迟扩展而不是通过%cutSpaceCount%
标准扩展来扩展它。
您应该使用类似于"double delayed“的东西,即类似于下面的结构:
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
发布于 2018-05-29 09:31:33
您似乎对调用延迟扩展时发生的操作顺序感到非常困惑。
首先,用%var%
替换var
的值。
然后!使用结果进行评估。
该操作序列的范围是一条逻辑线路,其可以是一条物理线路或用终端^
或更常见地使用带括号的线路序列继续的任意数量的物理线路。
然后在你的主线中,
CALL :get_substring string substringLength substring
ECHO !string!
ECHO !substring!
ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
由于这些语句不在同一逻辑行中,因此将分别计算它们,因此!var!
==%var%
。
在您的子例程(非IF版本)中,
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!
作为第二个操作执行。
每个echo
es都是一个独立的语句,并且!
可以(最好应该)被%
取代。
set /a
语句--好吧,set /a
允许不加修饰地使用变量的当前值,因此在这里使用SET /A cutSpaceCount=substringLength+1
或SET /A cutSpaceCount=%substringLength%+1
不会产生任何逻辑效果。
ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
将根据先前代码序列建立的值进行评估。
然而,当您添加if
时,代码是用括号括起来的,因此会变成一条逻辑语句,并以不同的方式运行。
然后,echo
es需要!
,因为您希望在代码块中显示修改后的值。由于在代码块的开头未设置cutSpaceCount
,因此SET string=!string:~%cutSpaceCount%!
将被计算为SET string=!string:~!
然后,当遇到IF
时,ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
将适当地替换变量的值
因此,替换例程可能是
: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
发布于 2018-05-29 17:58:33
正如其他人已经解释的那样,问题在于线路:
SET string=!string:~%cutSpaceCount%!
因为您对在同一逻辑行/代码块中更改的变量cutSpaceCount
使用立即展开(%
)。
一种可能的解决方案是像这样使用call
:
call set "string=%%string:~!cutSpaceCount!%%"
call
引入了另一个变量扩展阶段,因此序列如下:
%%
变为%
:call set "string=%string:~!cutSpaceCount!%"
5
):call
引入call set "string=%string:~5%"
%string:~5%
.https://stackoverflow.com/questions/50574549
复制相似问题