我应该在batch file中使用哪种评论风格?
我一直在写一些batch file,我遇到了这个用户指南 ,这已经很丰富。 有一件事告诉我,行可以被评论,不仅与REM
,而且::
。 它说:
批处理代码中的注释可以通过使用双冒号进行,这比使用REM命令更好,因为标签是在redirect符号之前处理的。
::<remark>
不会造成问题,但rem <remark>
会产生错误。
那为什么呢,我所看到的大多数指南和例子都使用了REM
命令? 是否::
在所有版本的Windows上工作?
tl; dr: REM
是在batch file中embedded批注的logging和支持的方式。
::
实质上是一个永远不会被跳到的空白标签,而REM
是一个没有任何作用的实际命令。 在任何情况下(至less在Windows 7上)redirect操作符的存在都会导致问题。
但是,在某些情况下, ::
被认为是行为不当,被parsing的不是标签而是某种盘符。 我对这个地方有点模糊不清,但是这足以让我完全使用REM
。 这是在batch file中embedded注释的logging和支持的方式,而::
仅仅是特定实现的工件。
编辑
这是一个例子,其中::
在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
当试图将输出redirect到一个文件时,问题就出现了。 我最好的猜测是它将::
解释为一个名为: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
对于angular色;
也是允许的一种;,:\/=
REM的速度比::
慢6倍左右(在Win7SP1上testing了100000条注释)。
对于一个正常的使用情况来说,这并不重要(58μs比360μs每注释行)
评论::
A ::
总是执行行结束符。
:: This is also a comment^ echo This line is also a comment
标签和注释标签 ::
在括号内有一个特殊的逻辑。
它们总是跨越两行SO:goto command not working 。
所以不推荐使用括号,因为它们通常是语法错误的原因。
ECHO ON
在REM
线上显示,但不是一行评论::
两者都不能真正注释掉其余部分,所以简单的%~
会导致语法错误。
REM This comment will result in an error %~ ...
但是,即使在特殊字符阶段完成之前,REM也能够在早期阶段停止批parsing器。
@echo ON REM This caret ^ is visible
您可以使用 &REM或&::在命令行末尾添加注释。 这种方法是有效的,因为'&'在同一行上引入了一个新的命令。
有百分号的评论%= comment =%
存在百分号的评论风格。
实际上这些都是可变的,但是它们被扩大到了没有。
但好处是可以放在同一条线上,即使没有&
。
等号确保这样一个variables不能存在。
echo Mytest set "var=3" %= This is a comment in the same line=%
批处理macrosbuild议使用百分比样式,因为它不会更改运行时行为,因为在定义macros时将删除注释。
set $test=(%\n% %=Start of code=% ^ echo myMacro%\n% )
当我意识到我可以使用label ::
来发表评论和注释代码REM
对我来说简直是丑陋的。 正如前面提到的那样,在使用inside ()
被阻塞的代码时,双冒号可能会导致问题,但是我发现了在标签::
和:
space之间交替的解决方法
:: This, of course, does :: not cause errors. ( :: But : neither :: does : this. )
它不像REM
那么丑陋,实际上给你的代码增加了一点风格。
所以在代码块之外我使用::
而在它们之间我交替::
和:
。
顺便说一下,对于大批量的评论,就像在你的batch file头部,你可以通过简单的注释来避免特殊的命令和字符。 这就让你使用任何你想要的标记方法或样式,尽pipe事实上如果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 . . .
使用你想要的任何符号*
,s等。
另一种select是将评论expression为一个总是展开为无形的variables扩展。
variables名称不能包含=
,除了未logging的dynamicvariables,如%=ExitCode%
和%=C:%
。 在第一个位置之后,没有variables名可以包含一个=
。 所以我有时使用以下内容在括号内包含注释:
::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)评论不能包含:
这个答案试图在这个页面上的许多伟大的答案的务实总结 :
杰布的伟大的答案值得特别提及,因为它确实深入并涵盖了许多边缘情况。
值得注意的是,他指出, 一个错误的variables/参数引用如%~
可能会破坏下面的任何解决scheme – 包括REM
行 。
全线评论 – 唯一直接支持的风格:
-
REM
(或其变种)是唯一的正式评论构造 ,是最安全的select – 请参阅Joey的有用答案 。 -
::
是一个(广泛使用的) 黑客 ,它有利弊 :-
优点 :
- 视觉上的独特性和可能的打字便利性。
- 速度 ,虽然这可能很less有关系 – 看到杰布的伟大的答案和罗伯· 范德沃德 的优秀的博客文章 。
-
缺点 :
- 里面
(...)
块,::
可以打破命令 , 安全使用的规则是限制性的,不容易记住 – 见下文。
- 里面
-
如果你想使用::
,你有这些select:
- 或者 :为了安全起见,在
(...)
块内部设置一个例外,并在那里使用REM
,或者不要在里面放置注释(...)
。 - 或者 :记住安全使用
::
inside(...)
的痛苦限制性规则,这些规则在以下代码片段中进行了总结:
@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
部分; 例如SET "foo=bar"
。 [1]
在这种情况下,我们可以区分两个亚型:
-
EOL的评论 (可以放在行尾),可以放在命令之后,总是延伸到行尾(再次, jeb的答案 ):
-
ver & REM <comment>
利用REM
是一个有效的命令,&
可以用来在现有命令之后放置一个额外的命令。 -
ver & :: <comment>
可以工作,但实际上只能在(...)
块之外使用,因为它的安全使用比使用::
standalone更有限。
-
-
行内注释 ,放置在一条线上的多个命令之间,或者理想地甚至在给定命令的内部 。
在线评论是最灵活的(单行)forms, 可以根据定义也可以用作EOL评论。-
ver & REM^. ^<comment^> & ver
ver & REM^. ^<comment^> & ver
允许在命令之间插入注释 (同样,由jeb的答案提供 ),但请注意<
和>
需要如何转义,因为后面的字符。 不能按原样使用:< > |
(而非转义&
或&&
或||
开始下一个命令)。 -
%= <comment> =%
,正如dbenham的伟大答案所详述的那样 ,是最灵活的forms ,因为它可以放在一个命令(参数中)中 。
它利用variables扩展语法来确保expression式始终扩展为空string – 只要注释文本既不包含%
也不包含:
像REM
一样,%= <comment> =%
在外部和内部(...)
块都可以很好地工作,但它在视觉上更有特色。 唯一的缺点是打字难,语法错误容易,而且广为人知,这会阻碍对使用该技术的源代码的理解。
-
多行(全行块)评论 :
-
James K的答案显示了如何使用
goto
语句和标签来限定任意长度和内容的多行注释(在他的情况下用于存储使用信息)。 -
Zee的答案显示了如何使用“空标签”创build一个多行注释,尽pipe必须注意用
^
来终止所有的内部行。 -
Rob van der Woude的博客文章提到了另一个有些模糊的选项,它允许你用任意数量的注释行结束一个文件 :一个开放
(
只会导致所有后来被忽略的东西 ,只要它不包含(非-^
-escaped))
,也就是说,只要块没有closures 。
[1]使用SET "foo=bar"
定义variables – 即在名称和=
和名称的组合中加上双引号 – 在SET "foo=bar" & REM Set foo to bar.
等命令中是必要的。 SET "foo=bar" & REM Set foo to bar.
,以确保遵循预期的variables值(直到下一个命令,在这种情况下是单个空间)不意外地成为其一部分。
(另外: SET foo="bar"
不但不能避免这个问题,而且会使双引号成为值的一部分 )。
请注意,这个问题是SET
所固有的,甚至适用于值后面的意外尾随空白,所以build议始终使用SET "foo=bar"
方法。
这个页面告诉我们,在一定的限制条件下使用“::”会更快。select时只需要考虑一下
很好的问题…我一直在寻找这个function太久…
经过几个testing和技巧,似乎更好的解决scheme是更明显的一个…
– >最好的办法,我发现这样做,防止parsing器完整性失败,重用REM:
echo this will show until the next REM &REM this will not show
你也可以使用多行与“空标签”的伎俩…(不要忘记^连续的行末)
::(^ this is a multiline^ comment... inside a null label!^ dont forget the ^caret at the end-of-line^ to assure continuity of text^ )
关于这个主题的非常详细的分析讨论可以在这个页面上find
它有示例代码和不同选项的优缺点。
James K,我很抱歉,我说的话很不公平。 我做的testing如下:
@ECHO OFF ( :: But : neither :: does : this :: also. )
这符合你对交替的描述,但是在这个时候出现了意外。 错误信息。
我今天进行了一些更进一步的testing,发现交替不是关键,但似乎关键是具有偶数行,没有以双冒号(::)开头的任何两行,并且不以双冒号。 考虑以下几点:
@ECHO OFF ( : But : neither : does : this : cause : problems. )
这工作!
但也要考虑到这一点:
@ECHO OFF ( : Test1 : Test2 : Test3 : Test4 : Test5 ECHO. )
有一个偶数的评论规则似乎并不适用于以命令结尾时。
不幸的是,这只是松鼠足够,我不知道我想使用它。
真的,最好的解决scheme,以及我能想到的最安全的方法是,如果像Notepad ++这样的程序将REM读取为双冒号,然后在保存文件时将双冒号写回REM语句。 但我不知道这样的程序,我不知道有任何插件Notepad ++那样做。