3

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

3 回答 3

5

这个问题有两个方面。首先,goto打破任何嵌套 IF/FOR 命令的事实,但也许更重要的是,While 组装起来goto非常慢。一种解决方案是用无限循环模拟一个while:并通过a在子例程中for /L %%i in () do ...打破它。goto这个解决方案的问题是for /L不能goto 在同一个 cmd.exe 上下文中破坏 a 。因此,解决方案是调用一个新的 cmd.exe 来执行 While。

在新的 cmd.exe 中执行的 Batch 文件可能是同一个调用者文件,所以我们需要通过同一个 Batch 文件中的特殊参数来控制 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
)

这篇文章详细解释了这个主题

于 2012-06-30T12:26:48.120 回答
3

Harry 在他的回答中使用子程序的想法是正确的。通常,一旦调用子例程,就无法访​​问外部循环 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
于 2012-06-30T05:26:08.490 回答
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
于 2012-06-30T02:23:44.347 回答