有关批处理*.bat文件中注释和速度的问题

3
我经常使用 :: 来开始注释。 现在我有一个 IF 块,发现如果多行 :: 注释在 IF 块中,则在 *.bat 文件中无法工作。 我找到了这个网站 https://www.robvanderwoude.com/comments.php ,这个网站解释了关于 *.bat 文件中的注释的许多内容。
通常情况下,注释是由 REM 命令启动的。 如该网站所述...... 在每个 REM 命令上,cmd 解释器将忽略该行,但会重新读取整个文件以获取 REM 之后的下一行,这会使整个过程变慢。
但是,:: 注释将被解释为无效的 GOTO 标签,因此解释器只会跳转到下一行,不会重新读取文件,因此处理速度更快。
现在我还有一个想法,在该网站上没有讨论:
使用 false IF-Block 创建注释。
IF defined COMMENTBLOCK (
    Write
    Your multiline
    comment here.
)

由于变量COMMENTBLOCK未定义,解释器将不会查看IF命令块内的内容,并跳过块内的注释。

现在在这个站点上,有人在谈论进程速度。 我认为解释器将检查变量COMMENTBLOCK,并且因为它未定义,会读取所有行直到块的末尾,然后继续进行处理。 我认为但不能确定,它不会像使用REM命令那样重新读取*.bat文件,并且它将在IF或FOR块中工作,相反,::注释不适用于IF或FOR块,如果注释是多行。

现在我如何测量*.bat文件的速度,以找出每种注释方法之间的速度差异? 我该如何确定......

IF defined COMMENTBLOCK (
    Multiline
    Comment
)

... 速度快如

:: Multiline
:: Comment

我该如何证明......

REM Multiline
REM Comment
...将比其他注释方法更慢吗?
这种*.bat文件非常快...差异可能在一秒以下,%time%变量以小时、分钟、秒和百分之一秒显示...
但是跳过这样的注释似乎甚至不需要更少的时间...因此结果实际上只是一个逻辑估计。
而且我没有软盘来查看如果使用软盘会发生什么。
也许最好的方法是有人知道,如果出现错误的未定义IF块,解释器会执行类似于false标签::或REM的操作...
使用错误的IF块作为FOR和IF块内的多行注释存在什么缺点呢?
非常感谢您的说明...
更新:使用未定义变量作为COMMENTBLOCK的方法无法处理管道|或闭合括号)...
IF defined COMMENTBLOCK (
    )
    |
    This will fail!!!
)

:: 和 REM 的方法可以处理任何东西,包括竖线 |

:: |
REM |

但是 :: 注释不能在 IF 和 FOR 等块中使用

另一种多行注释的奇怪方法是将两个命令放在一行上,例如 echo sometext & pause,但是需要用一个无效的跳转标签 :: 替换 pause 命令,然后在每行结尾加上 ^ 来添加新行,这需要在每个注释行之间保留空行,并且为了使每行保持在一起,每行都必须使用 ^ 进行换行。

echo some command &:: ^
_^
Strange characters do work ^
_^
but quotes are sensitive, they must be even ^
_^
last line of comment

另一种创建多行注释的方法是使用%= comment =%行...
%= multiline =%
%= comment   =%

虽然这样做也有缺点,但是在注释中使用%、!、%~等字符会使解释器混淆,特殊字符可以通过笨拙的方式进行转义 %= %% ~f0 =%

更多信息请参阅下面的评论,并表示感谢


大多数你所寻求的理解都在这里解释了:https://dev59.com/6G855IYBdhLWcg3w5Igb#4095133。批处理测试某个东西速度的一般方法是重复足够次数以确定你要比较的事物之间的可行基线。 - T3RR0R
对于多行注释的另一种选择,您可能尚未考虑过,请查看此链接:https://www.dostips.com/forum/viewtopic.php?p=23452#p23452。 - Compo
即使变量COMMENTBLOCK未定义,该块仍然会被读取;将无效语法echo|放置在块内,您将会收到一个错误... - aschipfl
1个回答

3
在每个REM命令中,cmd解释器将忽略该行但重新读取整个文件。
即使对于旧的command.com(MS DOS 6.22),这似乎是错误的。 但是REM仍然比较慢,这取决于使用方式。
在FOR块内部,差异非常大,因为REM将在每个循环中被解析和执行,但::(也适用于%= =%注释样式)将被解析并完全从代码中删除。对于重复块,REM需要时间,但::根本不需要时间!
在普通代码中,差异仅为解析和单次注释执行。 但是,即使在那里REM也需要约50%的额外时间。
例:
set "start=%time%"
FOR /L %%# in (1,1,1000) DO (
  call :test
)
set "end=%time%"
call :showdiff "%start%" "%end%" -<loop-call-overhead constant>
exit /b

:test
REM 1
REM 2
REM 3
REM 4
REM 5
REM 6
REM 7
REM 8
REM 9
REM 10
exit /b

循环执行10000次REM
:test函数为空(只包含exit /b)时,测量循环调用开销常数。 REM版本需要大约3000毫秒,而::版本需要大约2000毫秒。
在我的系统中,单个REM需要大约0.3毫秒,而::需要0.2毫秒。

“:: version” 在这个测试比较中是否有以“::”开头而不是“REM”的10行注释?这似乎是 REM 行显示的脚本与未显示的 :: 版本之间的区别。 - JohnH
@JohnH 是的,你说得对。我不想显示没有任何好处的那么多行。而且添加另一个标签的 :: version 也不是一个好主意,因为标签本身的文件位置对于测量时间是相关的,因此必须替换该块。 - jeb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接