我一直在写一些批处理文件,然后我看到了这个用户指南,它提供了很多信息。它告诉我的一件事是,行不仅可以用REM进行注释,还可以用::进行注释。它说:

批处理代码中的注释可以通过使用双冒号来生成,这比使用REM命令更好,因为标签在重定向符号之前被处理。::<remark>不会引起任何问题,但是rem <remark>会产生错误。

那么,为什么我看到的大多数指南和示例都使用REM命令呢?::适用于所有版本的Windows吗?


当前回答

关于这个话题的一个非常详细和分析性的讨论可以在这个页面上找到

它有示例代码和不同选项的优点/缺点。

其他回答

在批处理文件中注释有多种方法

1)使用快速眼动

这是官方的做法。它的执行时间显然比::要长,尽管它显然会在插入符号被处理之前提前停止解析。百分比展开发生在rem和::被识别之前,因此如果百分比存在,不正确的百分比使用,例如%~将导致错误。在代码块的任何地方使用都是安全的。

2)使用标签:,::或:;等。

For :: comment, ': comment' is an invalid label name because it begins with an invalid character. It is okay to use a colon in the middle of a label though. If a space begins at the start of label, it is removed : label becomes :label. If a space or a colon appears in the middle of the label, the rest of the name is not interpreted meaning that if there are two labels :f:oo and :f rr, both will be interpreted as :f and only the later defined label in the file will be jumped to. The rest of the label is effectively a comment. There are multiple alternatives to ::, listed here. You can never goto or call a ::foo label. goto :foo and goto ::foo will not work.

They work fine outside of code blocks but after a label in a code block, invalid or not, there has to be a valid command line. :: comment is indeed another valid command. It interprets it as a command and not a label; the command has precedence. Which is the command to cd to the :: volume, which will work if you have executed subst :: C:\, otherwise you get a cannot find the volume error. That's why :; is arguably better because it cannot be interpreted in this way, and therefore is interpreted as a label instead, which serves as the valid command. This is not recursive, i.e, the next label does not need a command after it. That's why they come in twos.

你需要在标签后面提供一个有效的命令,例如echo something。代码块中的标签必须至少带有一个有效命令,因此行是成对的。如果下一行有空格或右括号,你会得到一个意外的错误。如果在两个::行之间有一个空格,你将得到一个无效的语法错误。

你也可以像这样在::注释中使用插入符:

@echo off

echo hello
(
   :;(^
   this^
   is^
   a^
   comment^
   )
   :;
)
   :;^
   this^
   is^
   a^
   comment
   :;
) 

但你需要后面的:;出于上述原因。

@echo off

(
echo hello
:;
:; comment
:; comment
:;
)
echo hello

只要是偶数就可以。这无疑是最好的评论方式——用4行:;:;你不会得到任何需要使用2> nul或subst:: C:\来抑制的错误。你可以使用subst:: C:\来消除卷未发现错误,但这意味着你必须在代码中加入C:,以防止你的工作目录变成::\。

在一行的末尾注释 Command &::或Command & rem注释,但仍然必须是一个偶数,就像这样:

@echo off

(
echo hello & :;yes
echo hello & :;yes
:;
)

echo hello

第一个回显hello &:;yes在下一行有一个有效的命令,但第二个&:;yes没有,所以它需要一个,即:;。

3)使用无效的环境变量

%= comment =%. In a batch file, environment variables that are not defined are removed from the script. This makes it possible to use them at the end of a line without using &. It is custom to use an invalid environment variable i.e. one that contains an equals sign. The extra equals is not required but makes it look symmetrical. Also, variable names starting with "=" are reserved for undocumented dynamic variables. Those dynamic variables never end with "=", so by using an "=" at both the start and end of the comment, there is no possibility of a name clash. The comment cannot contain % or :.

@echo off 
echo This is an example of an %= Inline Comment =% in the middle of a line.

4)作为命令,将stderr重定向为nul

@echo off
(
echo hello
;this is a comment 2> nul
;this is another comment  2> nul
)

5)在文件末尾,未闭括号后面的所有内容都是注释

@echo off
(
echo hello
)

(this is a comment
this is a comment
this is a comment

REM是在批处理文件中嵌入注释的有文档支持的方法。


::本质上是一个永远不能跳转到的空白标签,而REM是一个实际的命令,它什么也不做。在这两种情况下(至少在Windows 7上),重定向操作符的存在都不会导致问题。

然而,在某些情况下,::在块中表现不佳,不是作为标签而是作为某种驱动器号进行解析。我不太清楚具体在哪里,但仅此一点就足以让我只使用快速眼动。它是在批处理文件中嵌入注释并得到支持的方法,而::仅仅是特定实现的工件。


下面是一个例子,其中::在FOR循环中产生一个问题。

这个例子在桌面上的test.bat文件中不起作用:

@echo off
for /F "delims=" %%A in ('type C:\Users\%username%\Desktop\test.bat') do (
    ::echo hello>C:\Users\%username%\Desktop\text.txt
)
pause

虽然这个例子将正确地作为注释工作:

@echo off
for /F "delims=" %%A in ('type C:\Users\%username%\Desktop\test.bat') do (
    REM echo hello>C:\Users\%username%\Desktop\text.txt
)
pause

问题似乎出现在试图将输出重定向到文件时。我的最佳猜测是,它将::解释为一个名为:echo的转义标签。

REM评论

REM可以注释一个完整的行,也可以注释行尾的多行插入号,如果它不是第一个标记的结束的话。

REM This is a comment, the caret is ignored^
echo This line is printed

REM This_is_a_comment_the_caret_appends_the_next_line^
echo This line is part of the remark

REM后面跟着一些字符。:\/=的工作方式有点不同,它不注释&号,所以你可以把它用作内联注释。

echo First & REM. This is a comment & echo second

但为了避免现有文件(如REM、REM.bat或REM;.bat)出现问题,应该只使用经过修改的版本。

REM^;<space>Comment

对于角色来说;也允许有;,:\/=

REM大约比::慢6倍(在Win7SP1上测试,有100000条注释行)。 对于正常使用来说,这并不重要(58µs vs 360µs /注释行)

评论:

A::总是执行行结束插入符。

:: This is also a comment^
echo This line is also a comment

标签和注释标签::在括号块中有一个特殊的逻辑。 它们总是跨越两行SO: goto命令不工作。 因此,不建议在括号块中使用它们,因为它们通常会导致语法错误。

使用ECHO ON显示REM行,但不显示注释为::

两者都不能真正注释掉该行的其余部分,因此简单的%~将导致语法错误。

REM This comment will result in an error %~ ...

但是REM能够在早期阶段停止批处理解析器,甚至在特殊字符阶段完成之前。

@echo ON
REM This caret ^ is visible

您可以使用& rem或&::在命令行末尾添加注释。 这种方法有效,因为'&'在同一行上引入了一个新命令。

带有百分号%= comment =%的注释

存在一个带有百分号的注释样式。

实际上,这些是变量,但它们被展开为零。 但优点是它们可以放在同一行中,即使没有&。 等号保证了这样一个变量不存在。

echo Mytest
set "var=3"     %= This is a comment in the same line=%

对于批处理宏,建议使用百分比样式,因为它不会改变运行时行为,因为在定义宏时注释将被删除。

set $test=(%\n%
%=Start of code=% ^
echo myMacro%\n%
)

性能REM vs:: vs %= =%

简而言之:

::和%= =%似乎具有相同的性能 REM的时间比: 在块中,特别是循环中,只有REM消耗时间,但是::在解析块时从缓存块中删除,因此它不消耗时间

有关更多信息,请参阅SO:关于批处理*.bat文件中的注释和速度的问题

另一种替代方法是将注释表示为一个总是展开为零的变量展开。

变量名不能包含=,除了未记录的动态变量,比如 %=ExitCode%和%=C:%。任何变量名都不能在第一个位置后面包含=。所以我有时会使用下面的代码在括号内包含注释:

::This comment hack is not always safe within parentheses.
(
  %= This comment hack is always safe, even within parentheses =%
)

它也是一种合并内联注释的好方法

dir junk >nul 2>&1 && %= If found =% echo found || %= else =% echo not found

前导=不是必须的,但我喜欢它的对称性。

有两个限制:

1)注释不能包含%

2)评论不能包含:

当我意识到我可以使用label::来注释和注释代码时,REM对我来说只是看起来很难看。如前所述,双冒号在()阻塞代码中使用时可能会导致问题,但我发现了一种变通方法,即在标签::和:空格之间交替使用

:: This, of course, does
:: not cause errors.

(
  :: But
   : neither
  :: does
   : this.
)

它不像REM那样丑陋,而且实际上为你的代码添加了一点风格。

所以在代码块之外,我使用::,在代码块内部,我在::和:之间交替。

顺便说一下,对于大量注释,比如批处理文件的头,您可以通过浏览注释来完全避免使用特殊命令和字符。这让你可以使用任何你想要的方法或风格的标记,尽管事实是,如果CMD实际上试图处理这些行,它会抛出一个嘘声。

@echo off
goto :TopOfCode

=======================================================================
COOLCODE.BAT

Useage:
  COOLCODE [/?] | [ [/a][/c:[##][a][b][c]] INPUTFILE OUTPUTFILE ]

Switches:
       /?    - This menu
       /a    - Some option
       /c:## - Where ## is which line number to begin the processing at.
         :a  - Some optional method of processing
         :b  - A third option for processing
         :c  - A forth option
  INPUTFILE  - The file to process.
  OUTPUTFILE - Store results here.

 Notes:
   Bla bla bla.

:TopOfCode
CODE
.
.
.

使用任何你想要的符号*,@等等。