我有一个做这件事的诀窍!
我想出了这个方法,因为在CLI上,不可能使用其他答案中提供的方法,这一直困扰着我。
我把它叫做“Do Until Break”或“无限”循环:
基本示例
FOR /L %L IN (0,0,1) DO @(
ECHO. Counter always 0, See "%L" = "0" - Waiting a split second&ping -n 1 127.0.0.1>NUL )
这真的是一个无限循环!
这对于在 CMD
窗口中监视某些内容非常有用,允许您在完成后使用 CTRL
+C
来中断它。
想要计数器吗?
可以使用 SET /A
或修改 FOR /L
循环进行计数,仍然是无限循环(请注意,这两种方法都存在32位整数溢出的问题)
SET /A
方法:
FOR /L %L IN (0,0,1) DO @(
SET /A "#+=1"&ECHO. L Still equals 0, See "%L = 0"! - Waiting a split second &ping -n 1 127.0.0.1>NUL )
原生的 FOR /L
循环计数器:
FOR /L %L IN (-2147483648,1,2147483648) DO @(
ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL )
计算4294967295个集合并显示L的当前值:
FOR /L %L IN (1,1,2147483648) DO @(
(
IF %L EQU 0 SET /A "#+=1">NUL
)&SET /A "#+=0"&ECHO. Sets of 4294967295 - Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL )
然而,如果:
- 您有兴趣查看监视器的输出,并担心在完成后检查之前我会通过9999行缓冲区限制。
- 一旦我正在监视的事物完成,您想要采取一些额外的行动。
为此,我确定了如何使用几种方法有效地中断FOR
循环,从而将其转换为“DO WHILE
”或“DO UNTIL
”循环,在CMD中否则极为缺乏。
注意:大多数情况下,循环将继续迭代超过您检查的条件,通常这是一种想要的行为,但不适用于我们的情况。
将“无限循环”转换为“DO WHILE
”/“DO UNTIL
”循环
更新:由于希望在CMD脚本(并使它们持久存在!)以及CLI中使用此代码,并且考虑是否可能存在“更正确”的实现方法,我建议使用新方法!
新方法(可在CMD脚本内部使用而不退出脚本):
FOR /F %%A IN ('
CMD /C "FOR /L %%L IN (0,1,2147483648) DO @( ECHO.%%L & IF /I %%L EQU 10 ( exit /b ) )"
') DO @(
ECHO %%~A
)
在命令行界面:
FOR /F %A IN ('
CMD /C "FOR /L %L IN (0,1,2147483648) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b ) )"
') DO @(
ECHO %~A
)
原始方法(在命令行界面上可以正常工作,但会终止脚本执行。)
FOR /L %L IN (0,1,2147483648) DO @(
ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL&(
IF /I %L EQU 10 (
ECHO.Breaking the Loop! Because We have matched the condition!&DIR >&0
)
)
) 2>NUL
旧的帖子内容
偶然间,我发现了一些退出循环的方法,这些方法不会在尝试做其他事情时关闭CMD提示符,这给了我一个想法。
注意:
虽然 ECHO.>&3 >NUL
在某些情况下对我起作用,但是多年来我一直在尝试和测试,发现 DIR >&0 >NUL
更加稳定可靠。
从现在开始,我将重新编写这个答案,使用更好的方法:上面提到的 DIR >&0 >NUL
。
改进后的帖子内容如下:
DIR >&0 >NUL
>NUL是可选的,我只是更喜欢不输出错误。
我尽可能地喜欢匹配inLine,就像您在这个经过清理的示例命令中看到的一样,我用它来监视我们VNX上的LUN迁移。
for /l %L IN (0,0,1) DO @(
ECHO.& ECHO.===========================================& (
[VNX CMD] | FINDSTR /R /C:"Source LU Name" /C:"State:" /C:"Time " || DIR >&0 >NUL
) & Ping -n 10 1.1.1.1 -w 1000>NUL )
此外,我在自己的笔记中找到了另一种方法,我刚刚重新测试了一下,确认它在CLI中同样有效。
显然,在我第一次发布帖子时,我发布了一个较旧的版本,而不是两个更好的新版本:
在这种方法中,我们使用EXIT /B
退出For循环,但我们不想退出CLI,因此我们将其包装在CMD会话中:
FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b ) )" ') DO @(ECHO %~A)
由于循环本身在CMD会话中发生,我们可以使用EXIT /B来退出循环的迭代,而不会丢失CMD会话,并且无需等待循环完成,这与其他方法类似。
我敢说,对于想要在CLI中中断for循环的情况,这种方法很可能是“预期”的方法,因为使用CMD会话也是CLI中获取延迟扩展工作的唯一方法,而此类行为显然是留下CMD会话的预期工作流程。
即:微软明显努力使CMD Exit /B For循环以这种方式运行,而使用我的另一种方法,则依赖于意外创建恰到好处的错误,以便在不让循环完成处理的情况下将您踢出循环,我仅偶然发现这种方法,并且似乎只在使用DIR命令时可靠地工作,这相当奇怪。
因此,我认为最好使用方法2:
FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b ) )" ') DO @(ECHO %~A)
虽然我怀疑方法1会略微更快:
FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( DIR >&) >NUL ) )
无论哪种情况,两者都应该允许您需要用于目的的DO-While循环。