WHILE循环中的FOR循环

时间:2012-06-30 01:04:48

标签: windows loops batch-file for-loop

我已经看到了解决此问题的部分的其他问题,但我没有看到完成整个事情的解决方案。当然,在命令处理器中没有“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...?
  )
)

3 个答案:

答案 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