首页 文章

我应该在批处理文件中使用哪种评论样式?

提问于
浏览
244

我一直在写一些批处理文件,我遇到了this user guide,这是非常有用的 . 它向我展示的一件事是,不仅可以使用 REM 来评论行,还可以使用 :: 进行评论 . 它说:

批处理代码中的注释可以使用双冒号,这比使用REM命令更好,因为标签在重定向符号之前处理 . :: <remark>没有问题,但rem <remark>会产生错误 .

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

9 回答

  • 149

    在我意识到我可以使用标签 :: 来发表评论并注释掉代码 REM 对我来说只是看起来很难看 . 如前所述,在 () 阻止代码中使用双冒号可能会导致问题,但我发现通过在标签 ::: 空格之间交替进行解决方法

    :: This, of course, does
    :: not cause errors.
    
    (
      :: But
       : neither
      :: does
       : this.
    )
    

    它不像 REM 那样丑陋,实际上为你的代码增加了一点风格 .

    所以在代码块之外我使用了 :: ,在它们里面我在 ::: 之间交替 .

    顺便说一句,对于大量的评论,例如批处理文件的 Headers ,您可以完全避免使用特殊命令和字符,只需通过评论即可 . 这让你使用你想要的任何方法或标记样式,尽管事实上如果 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
    .
    .
    .
    

    使用你希望的所有符号 *@ 等 .

  • 15

    这个答案试图在这个页面上的许多伟大的答案 pragmatic summary

    杰克的伟大答案值得特别提及,因为它真的深入并涵盖了许多优势案例 . 值得注意的是,他指出误解的变量/参数参考如%〜可以打破下面的任何解决方案 - 包括REM线 .


    整行评论 - 唯一直接支持的风格:

    • REM (或其大小写变体)是 only official comment construct ,是 safest choice - 请参阅Joey's helpful answer .

    • :: is a (widely used) hack ,其中有 pros and cons

    • Pros

    • 视觉独特性,可能还有打字的便利性 .

    • 速度,虽然这可能很少发生 - 请参阅jeb's great answerRob van der Woude's excellent blog post .

    • Cons

    • Inside (...) blocks, :: can break the commandrules for safe use are restrictive and not easy to remember - 见下文 .


    If you do want to use :: ,你有这些选择:

    • 要么:为了安全起见,在 (...) 块中创建一个例外并在那里使用 REM ,或者不要在 (...) 中放置注释 .

    • 或:记住 painfully restrictive rules for safe use of :: 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.
    )
    

    其他评论样式的模拟 - 内联和多行:

    请注意,批处理语言不直接支持这些样式,但可以进行模拟 .


    Inline comments

    *下面的代码片段使用ver作为任意命令的替代,以便于实验 . *要使SET命令与内联注释一起正常工作,请双引号name = value部分;例如,SET“foo = bar” . [1]

    在这种情况下,我们可以区分两种子类型:

    • EOL comments ([to-the-] end-of-line),可以放在一个命令之后,并且总是延伸到该行的末尾(同样,jeb's answer的礼貌):

    • ver & REM <comment> 利用 REM 是有效命令的事实, & 可用于在现有命令之后放置附加命令 .

    • ver & :: <comment> 也可以,但实际上只能在 (...) 块之外使用,因为它的安全使用比使用 :: standalone更有限 .

    • Intra-line comments ,它放在一行上的多个命令之间,或者理想情况下放在给定命令的内部 .
      内线评论是最灵活的(单行)形式和 can by definition also be used as EOL comments.

    • ver & REM^. ^<comment^> & ver 允许 inserting a comment between commands (再次,jeb's answer礼貌),但请注意 <> 需要 ^ -escaped,因为 the following chars. cannot be used as-is: < > | (而未转义的 &&&|| 启动下一个命令) .

    339 %= <comment> =% ,详见dbenham's great answer,是 most flexible form ,因为它是 can be placed inside a command (among the arguments) .
    它利用变量扩展语法,确保表达式始终扩展为空字符串 - as long as the comment text contains neither % nor :
    就像 REM 一样, %= <comment> =%(...) 块的外部和内部都很好用,但它在视觉上更有特色;唯一的缺点是它更难打字,更容易在语法上出错,而且不广为人知,这可能会妨碍对使用该技术的源代码的理解 .


    Multi-line (whole-line block) comments

    • James K's answer显示了如何使用 goto statement and a label 来分隔任意长度和内容的多行注释(在他的情况下,他用来存储使用信息) .

    • Zee's answer显示了如何使用 "null label" 创建多行注释,但必须小心终止所有内部行 ^ .

    • Rob van der Woude's blog post提到另一个有些模糊的选项,允许你到 end a file with an arbitrary number of comment lines :一个 opening ( only causes everything that comes after to be ignored ,只要它不包含(非 ^ -escaped) ) ,即只要该块没有关闭 .


    [1]使用SET“foo = bar”来定义变量 - 即在名称和=和值组合的位置加上双引号 - 在SET“foo = bar”和REM Set foo到bar等命令中是必需的 . 为了确保在预期的变量值之后(直到下一个命令,在这种情况下是单个空格)不会意外地成为其中的一部分 . (顺便说一下:SET foo =“bar”不仅不会避免问题,它会使双引号成为值的一部分) . 请注意,此问题是SET固有的,甚至适用于值后面的意外尾随空格,因此建议始终使用SET“foo = bar”方法 .

  • 24

    另一种选择是将注释表达为变量扩展,它总是扩展为空 .

    变量名称不能包含 = ,除了未记录的动态变量之外
    %=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)评论不能包含 :

  • 24

    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 的转义标签 .

  • 3

    This页面告诉我在某些约束条件下使用"::"会更快 . 选择时要考虑的事情

  • 7

    评论与REM

    如果 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
    

    而对于角色 ; 也允许 ;,:\/= 之一

    REM约为 6 times slower 而不是 :: (在Win7SP1上测试,有100000个注释行) .
    对于正常使用而言,它并不重要(每条评论线为58μs而不是360μs)

    评论::

    :: 始终执行行尾插入符号 .

    :: 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能够在早期阶段停止批处理解析器,甚至在特殊字符阶段完成之前 .

    @echo ON
    REM This caret ^ is visible
    

    You can use&REM或&::在命令行末尾添加注释 . 这种方法有效,因为'&'在同一行引入了一个新命令 .

    带百分号的评论%=评论=%

    存在具有百分号的评论样式 .

    实际上这些是变量,但它们被扩展为零 .
    但优点是它们可以放在同一条线上,即使没有 & .
    等号确保这样的变量不存在 .

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

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

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

    好问题......我一直在寻找这个功能...

    经过多次测试和技巧后,似乎更好的解决方案是更明显的...

    • 我发现这样做的最好方法,防止解析器完整性失败,重用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^ 
    )
    
  • 4

    詹姆斯K,对不起,我说的很公平 . 我做的测试如下:

    @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语句 . 但我不知道这样的程序,我也不知道任何用于记事本的插件 .

  • 315

    有关该主题的非常详细的分析性讨论,请参见THIS页面

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

相关问题