我已经看到了解决此问题的部分的其他问题,但我没有看到完成整个事情的解决方案。当然,在命令处理器中没有“while”这样的东西,并且由于goto:line语句突破了所有循环,因此它不能用于迭代特定持续时间的某些值集之前继续下一个值。
这是我正在寻找的逻辑流程的伪代码;命令处理器阻止了我到目前为止运行它的尝试。你将如何构建这个(除了抛弃批处理脚本并转到c#或其他东西)?
伪代码:
SET %%durationMinutes=60
FOR %%X IN (10 20 40 80 160 200 0) DO (
:: calculate elapsed minutes...
WHILE %elapsedMinutes < %%durationMinutes DO (
:: unrelated hocus pocus here, uses %%X as a variable
call :foo %%X
// can't use goto to simulate the WHILE loop since it breaks %%X, so...?
)
)
答案 0 :(得分:5)
这个问题有两个面孔。首先,goto
打破任何嵌套IF / FOR命令的事实,但也许更重要的是,与goto
汇编的while非常慢。一种解决方案是使用无限循环模拟一段时间:for /L %%i in () do ...
并通过子例程中的goto
将其分解。此解决方案的问题是for /L
不能在同一cmd.exe上下文中使用goto
打破。因此,解决方案是调用新的cmd.exe来执行While。
要在新cmd.exe中执行的批处理文件可能是同一个调用程序文件,因此我们需要通过同一批处理文件中的特殊参数来控制While的执行。此外,我们可以使用辅助变量来使所有东西更清晰。这是:
@echo off
setlocal EnableDelayedExpansion
rem While dispatcher
if "%1" equ "While" goto %2
rem Definition of auxiliary variables
set While=for /L %%a in () do if
set Do=(
set EndW=) else exit
set RunWhile=cmd /Q /C "%0" While
echo Example of While
echo/
goto RunMyWhile
rem Write the While code here
:MyWhile
set /A i=0, num=0
set /P "num=Enter number: "
%While% !num! gtr 0 %Do%
set /A i+=1
echo !i!- Number processed: !num!
echo/
set num=0
set /P "num=Enter number: "
%EndW% !i!
rem Execute the While here
:RunMyWhile
%RunWhile% MyWhile
set i=%errorlevel%
echo/
echo While processed %i% elements
如您所见,While可能会通过ERRORLEVEL将数字结果返回给调用者代码。
在您的特定情况下:
SET durationMinutes=60
goto RunMyWhile
:MyWhile
:: calculate elapsed minutes...
%WHILE% !elapsedMinutes! < %durationMinutes% %DO%
:: unrelated hocus pocus here, uses %3 as a variable
call :foo %3
:: calculate elapsed minutes again...
%EndW%
:RunMyWhile
FOR %%X IN (10 20 40 80 160 200 0) DO (
%RunWhile% MyWhile %%X
)
本主题在this post
详细解释答案 1 :(得分:3)
哈利有正确的想法在his answer中使用子程序。通常,一旦调用子例程,就无法访问外部循环FOR变量。但是如果子程序有自己的FOR循环,它们会“神奇地”再次可用。这可以消除将外循环值存储在变量中或将值作为参数传递的需要。
@echo off
for %%x in (1 2 3 4 5) do (
echo begin outer loop iteration, x=%%x
call :innerLoop
echo end of outer loop iteration, x=%%x
echo(
)
echo Outer loop complete
exit /b
:innerLoop
echo inside subroutine, x FOR variable is inaccessible: x=%%x
for %%y in (1 2 3 4 5) do (
if %%y gtr %%x goto :break
echo within FOR loop inside subroutine: x=%%x y=%%y
)
:break
echo end of subroutine, x FOR variable is inaccessible: x=%%x
exit /b
结果如下:
begin outer loop iteration, x=1
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=1 y=1
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=1
begin outer loop iteration, x=2
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=2 y=1
within FOR loop inside subroutine: x=2 y=2
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=2
begin outer loop iteration, x=3
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=3 y=1
within FOR loop inside subroutine: x=3 y=2
within FOR loop inside subroutine: x=3 y=3
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=3
begin outer loop iteration, x=4
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=4 y=1
within FOR loop inside subroutine: x=4 y=2
within FOR loop inside subroutine: x=4 y=3
within FOR loop inside subroutine: x=4 y=4
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=4
begin outer loop iteration, x=5
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=5 y=1
within FOR loop inside subroutine: x=5 y=2
within FOR loop inside subroutine: x=5 y=3
within FOR loop inside subroutine: x=5 y=4
within FOR loop inside subroutine: x=5 y=5
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=5
Outer loop complete
答案 2 :(得分:1)
只需将循环内容放在子程序中即可。这是一个简单例子的伪代码:
for x in (1 2 3 4 5) {
y = 1
while (y <= x) {
echo y
y = y + 1
}
echo Looping
}
批量实施:
for %%x in (1 2 3 4 5) do set x=%%x & call :for_loop
goto :for_end
:for_loop
set y=1
:while_loop
if not %y% LEQ %x% goto :while_end
echo %y%
set /a y=y+1
goto :while_loop
:while_end
echo Looping
goto :eof
:for_end
输出:
1
Looping
1
2
Looping
1
2
3
Looping
1
2
3
4
Looping
1
2
3
4
5
Looping