我应该在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 

但是为了避免像REMREM.batREM;.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 ONREM线上显示,但不是一行评论::

两者都不能真正注释掉其余部分,所以简单的%~会导致语法错误。

 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 ++那样做。