我一直在写一些批处理文件,然后我遇到了this user guide,它提供了很多信息。它向我展示的一件事是,行不仅可以使用REM
进行评论,还可以使用::
进行评论。它说:
批处理代码中的注释可以使用双冒号,这比使用REM命令要好,因为标签在重定向符号之前处理。
::<remark>
没有问题,但rem <remark>
会产生错误。
为什么然后,我看到的大多数指南和示例都使用REM
命令? ::
是否适用于所有版本的Windows?
答案 0 :(得分:329)
tl; dr: REM
是在批处理文件中嵌入评论的文档化和支持的方式。
::
本质上是一个永远不能跳转到的空白标签,而REM
是一个实际的命令,它什么都不做。在这两种情况下(至少在Windows 7上),重定向运算符的存在都会导致问题。
然而,::
已知在某些情况下会在块中行为不端,不是作为标签解析而是作为某种驱动器号解析。我对确切位置有点模糊,但仅此一点就足以让我独家使用REM
。这是在批处理文件中嵌入注释的文档化和支持的方式,而::
仅仅是特定实现的工件。
以下是::
在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
的转义标签。
答案 1 :(得分:151)
如果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倍(在带有100000条评论行的Win7SP1上测试)。
对于正常使用而言,它并不重要(58μs与每条评论线的360μs)
:: This is also a comment^
echo This line is also a comment
始终执行行结尾插入符号。
::
标签以及注释标签 ECHO ON
在括号内有一个特殊的逻辑。
它们总是跨越两行SO: goto command not working
因此,不建议将它们用于括号块,因为它们通常是语法错误的原因。
显示REM
时会显示::
行,但不会显示评论为%~
的行
两者都无法真正注释掉该行的其余部分,因此简单的REM This comment will result in an error %~ ...
将导致语法错误。
@echo ON
REM This caret ^ is visible
但REM能够在早期阶段停止批处理解析器,甚至在特殊字符阶段完成之前。
&
You can use&amp; REM或&amp; ::在命令行末尾添加注释。 这种方法有效,因为'&amp;'在同一行引入了一个新命令。
存在带百分号的评论样式。
实际上这些是变量,但它们被扩展为无
但优点是它们可以放在同一行,即使没有echo Mytest
set "var=3" %= This is a comment in the same line=%
等号确保这样的变量不存在。
set $test=(%\n%
%=Start of code=% ^
echo myMacro%\n%
)
建议批处理宏使用百分比样式,因为它不会更改运行时行为,因为在定义宏时将删除注释。
{{1}}
答案 2 :(得分:25)
另一种选择是将评论表达为变量扩展,它总是扩展为空。
变量名称不能包含=
,除了未记录的动态变量(如
)
%=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)评论不能包含:
答案 3 :(得分:24)
在我意识到我可以使用标签::
来发表评论并注释掉代码REM
时,我看起来很丑陋。如前所述,在()
阻止代码中使用双冒号可能会导致问题,但我发现通过在标签::
和:
之间交替进行解决方法空间
:: This, of course, does
:: not cause errors.
(
:: But
: neither
:: does
: this.
)
它并不像REM
那样丑陋,实际上为你的代码添加了一些风格。
因此,除了代码块之外,我使用::
并在其中我在::
和:
之间切换。
顺便说一句,对于大量的评论,例如批处理文件的标题,只需goto
注释你就可以完全避免使用特殊命令和字符。这让你可以使用你想要的任何方法或标记样式,尽管事实上如果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
.
.
.
使用您希望的*
,@
等符号。
答案 4 :(得分:17)
此回答尝试在此页面上的许多优秀答案的实用摘要:
jeb's great answer值得特别提及,因为它确实深入并涵盖了许多优势案例。
值得注意的是,他指出错误构造的变量/参数引用(例如%~
)可能会破坏以下解决方案的任何 - 包括REM
行。< / SUP>
REM
(或其案例变体)是唯一的官方评论构建,是最安全的选择 - 请参阅Joey's helpful answer。
::
是一个(广泛使用的) hack ,其利弊:
<强>赞成强>:
<强>缺点强>:
(...)
块内,::
可以打破命令,安全使用规则是限制性的,不容易记得 - 见下文。 如果您 想要使用::
,您有以下选择:
(...)
块内部设置例外并在其中使用REM
,或者不要将评论放在 {{ 1}}完全。(...)
中安全使用::
的痛苦限制性规则,这些规则在以下代码段中进行了总结:(...)
请注意,批处理语言不直接支持这些样式,但可以模拟。
内联评论:
*下面的代码片段使用@echo off
for %%i in ("dummy loop") do (
:: This works: ONE comment line only, followed by a DIFFERENT, NONBLANK line.
date /t
REM If you followed a :: line directly with another one, the *2nd* one
REM would generate a spurious "The system cannot find the drive specified."
REM error message and potentially execute commands inside the comment.
REM In the following - commented-out - example, file "out.txt" would be
REM created (as an empty file), and the ECHO command would execute.
REM :: 1st line
REM :: 2nd line > out.txt & echo HERE
REM NOTE: If :: were used in the 2 cases explained below, the FOR statement
REM would *break altogether*, reporting:
REM 1st case: "The syntax of the command is incorrect."
REM 2nd case: ") was unexpected at this time."
REM Because the next line is *blank*, :: would NOT work here.
REM Because this is the *last line* in the block, :: would NOT work here.
)
作为任意命令的替身,以便于实验。
*要使ver
命令与内联注释一起正常工作,请双引SET
部分;例如,name=value
。 [1]
功能
在这种情况下,我们可以区分两种亚型:
EOL评论([to-the-] end-of-line),可以放在命令之后,并且总是延伸到行尾(再次,礼貌) of jeb's answer):
SET "foo=bar"
利用ver & REM <comment>
是有效命令的事实,REM
可用于在现有命令之后添加其他命令。&
也适用,但实际上只能在ver & :: <comment>
块之外使用,因为它的安全使用比使用(...)
独立版更加有限。 内线注释,位于行上的多个命令之间,或理想情况下甚至是内部的给定命令。
内线注释是最灵活的(单线)形式,也可以用作EOL注释。
::
允许在命令之间插入评论 (同样,jeb's answer提供),但请注意{{1} }和ver & REM^. ^<comment^> & ver
需要<
- 转义,因为以下字符。不能按原样使用:>
(而未转义的^
或< > |
或&
启动 next 命令。 / p>
&&
,详见dbenham's great answer,最灵活的表单,因为可以放在里面命令(参数中)。
它以一种确保表达式始终扩展为空字符串 - 的方式利用变量扩展语法,只要注释文本既不包含||
也不包含{{1 }} 强>
与%= <comment> =%
一样,%
适用于:
块的内部和内部,但它在视觉上更具特色;唯一的缺点是键入更难,语法更容易出错,而且不广为人知,这可能会妨碍对使用该技术的源代码的理解。
多行(整行块)评论:
James K's answer展示了如何使用 REM
语句和标签来划分任意长度和内容的多行注释(在他的情况下,他是用于存储使用信息。)
Zee's answer展示如何使用&#34; null标签&#34; 创建多行注释,但必须小心终止所有内线与%= <comment> =%
。
Rob van der Woude's blog post提到另一个有些模糊的选项,允许您 结束一个包含任意数量注释行的文件: < em>只打开(...)
会导致之后的所有内容被忽略,只要它不包含(非goto
- 转义){{ 1}},即只要块不是关闭。
[1]使用^
定义变量 - 即在名称和(
和值组合周围加上双引号 - 在命令中是必要的作为^
,以确保跟随预期的变量值(直到下一个命令,在这种情况下是单个空格)不会意外地成为其中的一部分。
(顺便说一句:)
不仅不会避免这个问题,它会使双引号成为值的一部分。)
请注意,此问题是SET "foo=bar"
固有的问题,甚至适用于意外跟踪值后面的空格,所以建议始终使用{{ 1}}方法。
答案 5 :(得分:7)
This页面告诉您使用&#34; ::&#34;在某些限制下会更快 选择
时需要考虑的事情答案 6 :(得分:4)
好问题......我一直在寻找这个功能......
经过多次测试和技巧后,似乎更好的解决方案是更明显的一个...- &GT;我发现这样做的最好方法是防止解析器完整性失败,重用REM:
echo this will show until the next REM &REM this will not show
你也可以使用带有“NULL LABEL”技巧的多线... (不要忘记行末尾的^连续性)
::(^
this is a multiline^
comment... inside a null label!^
dont forget the ^caret at the end-of-line^
to assure continuity of text^
)
答案 7 :(得分:3)
@ECHO OFF
(
:: But
: neither
:: does
: this
:: also.
)
这符合您对交替的描述,但失败并且“)此时出乎意料。”错误信息。
我今天做了一些进一步的测试,发现交替不是关键,但看起来关键是有一个偶数行,没有任何两行连续以双冒号开头(::)而不是结束双冒号。请考虑以下事项:
@ECHO OFF
(
: But
: neither
: does
: this
: cause
: problems.
)
这个有效!
但也要考虑这个:
@ECHO OFF
(
: Test1
: Test2
: Test3
: Test4
: Test5
ECHO.
)
结束命令时,具有偶数条评论的规则似乎不适用。
不幸的是,这只是松散的,我不确定我是否想要使用它。
真的,最好的解决方案,也是我能想到的最安全的解决方案,就是像Notepad ++这样的程序会将REM作为双冒号读取,然后在保存文件时将双冒号写回REM语句。但我不知道这样的程序,我也不知道Notepad ++的任何插件也是如此。
答案 8 :(得分:2)
有关该主题的非常详细的分析性讨论可在THIS页面
上找到它有示例代码和不同选项的优缺点。
答案 9 :(得分:0)
批处理文件中有多种注释方式
1)使用rem
这是官方方式。尽管显然要在处理插入符号之前就停止解析,但执行显然比::
花费的时间更长。百分比扩展发生在rem和::
被识别之前,因此,如果存在百分比,则错误的百分比用法(即%~
)将导致错误。在代码块中的任何地方都可以安全使用。
2)使用标签:
,::
或:;
等。
对于:: comment
,':comment'是无效的标签名称,因为它开始带有无效字符。可以在标签中间使用冒号。如果空格始于标签的开头,则将其删除: label
变为:label
。如果标签中间出现空格或冒号,则不会解释名称的其余部分,这意味着如果有两个标签:f:oo
和:f rr
,则两者都将被解释为{{1} },仅文件中后来定义的标签将被跳转到。标签的其余部分实际上是注释。 here列出了:f
的多种选择。您永远不能::
或goto
标签call
。 ::foo
和goto :foo
不起作用。
它们在代码块之外可以正常工作,但是在代码块中的标签之后(无论是否有效),必须有一个有效的命令行。 goto ::foo
确实是另一个有效命令。它将其解释为命令而不是标签。该命令具有优先权。这是CD到:: comment
卷的命令,如果执行了::
,该命令将起作用,否则将出现找不到卷的错误。这就是subst :: C:\
之所以可以说更好的原因,因为它不能以这种方式解释,因此可以解释为标签,它是有效的命令。这不是递归的,即下一个标签不需要后面的命令。这就是为什么它们合二为一。
您需要在标签后提供有效的命令,例如:;
。代码块中的标签必须带有至少一个有效命令,因此,每两行成对出现。如果下一行有空格或右括号,则会出现意外的echo something
错误。如果两行)
之间有空格,则会收到无效的语法错误。
您也可以像这样在::
注释中使用插入符号运算符:
::
但是出于上述原因,您需要结尾的@echo off
echo hello
(
:;(^
this^
is^
a^
comment^
)
:;
)
:;^
this^
is^
a^
comment
:;
)
。
:;
只要有偶数就可以。毫无疑问,这是最好的注释方式-带有4行和@echo off
(
echo hello
:;
:; comment
:; comment
:;
)
echo hello
。使用:;
,您不会遇到需要使用:;
或2> nul
来消除的任何错误。您可以使用subst :: C:\
使找不到卷的错误消失,但这意味着您还必须在代码中放入C:,以防止工作目录成为subst :: C:\
。
要在行尾发表评论,您可以执行
::\
或command &::
,但仍然必须是偶数,如下所示:
command & rem comment
第一个@echo off
(
echo hello & :;yes
echo hello & :;yes
:;
)
echo hello
在下一行有一个有效命令,但第二个echo hello & :;yes
没有,因此它需要一个命令,即& :;yes
。
3)使用无效的环境变量
:;
。在批处理文件中,未定义的环境变量将从脚本中删除。这样就可以在一行的末尾使用它们,而无需使用%= comment =%
。通常使用无效的环境变量,即包含等号的环境变量。多余的相等不是必需的,但是使它看起来对称。同样,以“ =”开头的变量名称保留给未记录的动态变量。这些动态变量永远不会以“ =”结尾,因此通过在注释的开头和结尾使用“ =”,就不会发生名称冲突。注释不能包含&
或%
。
:
4)作为命令,将stderr重定向到nul
@echo off
echo This is an example of an %= Inline Comment =% in the middle of a line.
5)在文件末尾,未加括号的所有内容均为注释
@echo off
(
echo hello
;this is a comment 2> nul
;this is another comment 2> nul
)