Meh*_*dad 24 for-loop batch-file break
为什么这个批处理文件永远不会脱离循环?
For /L %%f In (1,1,1000000) Do @If Not Exist %%f Goto :EOF
Run Code Online (Sandbox Code Playgroud)
不应该Goto :EOF突破循环?
我想我应该更明确地问... 我怎么能摆脱循环?
@echo off
if "%1"=="loop" (
for /l %%f in (1,1,1000000) do (
echo %%f
if exist %%f exit
)
goto :eof
)
cmd /v:on /q /d /c "%0 loop"
echo done
Run Code Online (Sandbox Code Playgroud)
这个页面提出了一种在循环中使用goto的方法,它看起来确实有效,但在大循环中需要一些时间.所以在内部它在执行goto之前完成循环.
您可以简单地使用echo on,您将看到goto :eof甚至exit /b不能按预期工作.
循环内部的代码不再执行,但循环会针对所有数字进行扩展.
这就是它如此缓慢的原因.
退出FOR/L循环的唯一方法似乎是exitWimmel示例的变体,但这对于从循环中访问任何结果来说并不是非常快速也没有用.
这显示了10个扩展,但没有一个会被执行
echo on
for /l %%n in (1,1,10) do (
goto :eof
echo %%n
)
Run Code Online (Sandbox Code Playgroud)
我的回答
使用嵌套for循环为循环提供断点for /l。
for %%a in (0 1 2 3 4 5 6 7 8 9) do (
for %%b in (0 1 2 3 4 5 6 7 8 9) do (
for /l %%c in (1,1,10) do (
if not exist %%a%%b%%c goto :continue
)
)
)
:continue
Run Code Online (Sandbox Code Playgroud)
说明
必须对代码进行大量调整才能正确使用嵌套循环。例如,写入的内容会有前导零。可以使用简单的命令立即打破
“常规”循环,而循环则不能。此代码的最内层循环无法立即中断,但每 10 次迭代后就会出现一个整体断点(如所写)。最里面的循环不必是 10 次迭代——如果您选择执行 100 或 1000 或 2873 次(如果数学对循环很重要),您只需正确考虑数学即可。 forgotofor /lfor /l
历史 我在试图找出为什么某个脚本运行缓慢时发现了这个问题。事实证明,我使用了具有传统循环结构的多个循环:
set cnt=1
:loop
if "%somecriteria%"=="finished" goto :continue
rem do some things here
set /a cnt += 1
goto :loop
:continue
echo the loop ran %cnt% times
Run Code Online (Sandbox Code Playgroud)
该脚本文件变得有些长,并且是从网络驱动器运行的。这种类型的循环文件可能被调用 20 次,每次会循环 50-100 次。脚本文件运行时间太长。我有一个好主意,尝试将其转换为for /l循环。所需的迭代次数未知,但小于 10000。我的第一次尝试是这样的:
setlocal enabledelayedexpansion
set cnt=1
for /l %%a in (1,1,10000) do (
if "!somecriteria!"=="finished" goto :continue
rem do some things here
set /a cnt += 1
)
:continue
echo the loop ran %cnt% times
Run Code Online (Sandbox Code Playgroud)
随着echoon,我很快发现循环for /l仍然做了......一些事情......但实际上没有做任何事情。它运行得快得多,但仍然比我想象的要慢。因此,我发现了这个问题,并最终得出了上面提出的嵌套循环的想法。
旁注事实证明
,只需确保循环没有任何输出,就for /l可以大大加快循环速度。我能够这样做以显着提高速度:
setlocal enabledelayedexpansion
set cnt=1
@for /l %%a in (1,1,10000) do @(
if "!somecriteria!"=="finished" goto :continue
rem do some things here
set /a cnt += 1
) > nul
:continue
echo the loop ran %cnt% times
Run Code Online (Sandbox Code Playgroud)
如果您使用 call 而不是 goto ,则不需要单独的批处理文件来使用 exit /b 退出循环
call :loop
echo loop finished
goto :eof
:loop
FOR /L %%I IN (1,1,10) DO (
echo %%I
IF %%I==5 exit /b
)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,“exit /b”将退出“call”并从“call”之后的行继续,因此输出如下:
1
2
3
4
5
loop finished
Run Code Online (Sandbox Code Playgroud)
FOR /L在完成所有迭代之前不可能退出 a 。
FOR /L我已经调试了进程的执行cmd.exe。
Microsoft 可以更好地记录它并节省我们所有的精力。
事实:
while (TRUE),并且break仅在达到迭代限制时才会发生。EXIT /b或 aGOTO时,不再执行任何命令,直到迭代结束。EXIT当遇到an时,cmd.exe进程终止。测试:
12秒
FOR /L %%G in (1,1,5000000) do (ECHO Only once & GOTO :EOF)
Run Code Online (Sandbox Code Playgroud)
7秒
FOR /L %%G in (1,1,5000000) do (ECHO Only once & EXIT /b)
Run Code Online (Sandbox Code Playgroud)
0秒,但这会终止cmd.exe进程
FOR /L %%G in (1,1,5000000) do (ECHO Only once & EXIT)
Run Code Online (Sandbox Code Playgroud)
Tim*_*Tim -1
对此进行了一些研究,看来您正在从 1 循环到 2147483647,增量为 1。
(1, 1, 2147483647):第一个数字是起始数字,下一个数字是步骤,最后一个数字是结束数字。
编辑添加
看起来无论任何测试条件如何,循环都会运行到完成。我测试过
FOR /L %%F IN (1, 1, 5) DO SET %%F=6
Run Code Online (Sandbox Code Playgroud)
而且跑得很快。
第二次编辑
由于这是批处理文件中的唯一行,您可以尝试 EXIT 命令:
FOR /L %%F IN (1, 1, 2147483647) DO @IF NOT EXIST %%F EXIT
Run Code Online (Sandbox Code Playgroud)
但是,这也会关闭 Windowscmd提示窗口。
| 归档时间: |
|
| 查看次数: |
87141 次 |
| 最近记录: |