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

Mik*_*Hay 271 comments coding-style batch-file

我一直在编写一些批处理文件,并且我遇到了这个用户指南,该指南非常有用.它告诉我的一件事是线条不仅可以评论REM,还可以评论::.它说:

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

为什么那么,我看到的大多数指南和示例都使用REM命令?是否::在所有版本的Windows工作?

Joe*_*oey 343

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
Run Code Online (Sandbox Code Playgroud)

虽然此示例将正确地作为注释:

@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
Run Code Online (Sandbox Code Playgroud)

尝试将输出重定向到文件时似乎出现问题.我最好的猜测是,它是::一个被称为转义标签的解释:echo.

  • 漂亮的触摸添加了一个;博士 (14认同)
  • @mosh是对的.例如,`%VAR%`变量被扩展.假设你(错误地)`设置TARGET = C:\ Program Files(x86)\"foo.exe"`,并在`DO(..)`表达式中你有`:: echo%TARGET%`你会得到一个错误,因为`(x86)`被扩展_before_整个表达式被评估,导致一个无效的`DO(..)`表达式和_very_莫名其妙的错误(在这种情况下_"\ Microsoft此时是意外的"_) .你的表达式中甚至不需要`|`或`>`.但是```不是真正的评论,`REM`是. (4认同)
  • @Firedan:批处理文件的名称及其位置是否相关(以及要重定向到的文件的名称和位置?)。否则,简化示例会很好。 (2认同)
  • 如果行中的变量使用延迟,::将导致一些错误消息,例如找不到特定的磁盘驱动程序.....那么最好使用REM. (2认同)
  • ::解析注释,以及> |等特殊字符 结束评论,并且未评论以下文本. (2认同)

jeb*_*jeb 156

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
Run Code Online (Sandbox Code Playgroud)

REM后跟一些字符的.:\/=工作方式略有不同,它不会对&符号进行注释,因此您可以将其用作内联注释.

echo First & REM. This is a comment & echo second
Run Code Online (Sandbox Code Playgroud)

但是为了避免现有文件的问题REM,REM.bat或者REM;.bat只应使用修改后的变体.

REM^;<space>Comment
Run Code Online (Sandbox Code Playgroud)

并且对于角色;也允许其中之一;,:\/=

REM大约6倍::(在Win7SP1上测试,有100000个评论行).
对于正常使用而言,这并不重要(58μs与每条评论线360μs)

评论::

A ::始终执行线端插入符号.

:: This is also a comment^
echo This line is also a comment
Run Code Online (Sandbox Code Playgroud)

标签和注释标签 ::在括号块中具有特殊逻辑.
它们总是跨越两行SO:goto命令不起作用.
因此,不建议将它们用于括号块,因为它们通常是语法错误的原因.

随着ECHO ON一个REM线被示出,但没有一个符合注释::

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

REM This comment will result in an error %~ ...
Run Code Online (Sandbox Code Playgroud)

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

@echo ON
REM This caret ^ is visible
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

echo Mytest
set "var=3"     %= This is a comment in the same line=%
Run Code Online (Sandbox Code Playgroud)

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

set $test=(%\n%
%=Start of code=% ^
echo myMacro%\n%
)
Run Code Online (Sandbox Code Playgroud)

  • 应该注意的是,`%=`注释带有引号,即`set foo = bar%= baz`导致`foo`扩展为`bar%= baz`,`set foo ="bar"% = baz`,而只有`set"foo = bar"%= baz`导致`foo`按预期扩展到`bar`. (2认同)
  • @ LastStar007:通常值得推荐使用引号样式`set“ foo = bar”`,因为这是最可靠的形式,可以清楚地界定该值。您所描述的问题是_set`s_行为固有的,并不特定于`%=…=%`注释:除非您使用“ var = val”引用,否则set会考虑遵循“ =”值,包括尾随空格(行尾或下一个内联命令的开始)。 (2认同)

dbe*_*ham 27

另一种方法是将评论表达为变量扩展,它总是扩展为空.

变量名称不能包含=,除了未记录的动态变量,如
%=ExitCode%%=C:%.没有变量名称可以包含=在第一个位置之后.所以我有时使用以下内容在括号内的块中包含注释:

::This comment hack is not always safe within parentheses.
(
  %= This comment hack is always safe, even within parentheses =%
)
Run Code Online (Sandbox Code Playgroud)

它也是一种结合在线评论的好方法

dir junk >nul 2>&1 && %= If found =% echo found || %= else =% echo not found
Run Code Online (Sandbox Code Playgroud)

领先=是没有必要的,但我喜欢对称性.

有两个限制:

1)评论不能包含 %

2)评论不能包含 :

  • @JamesK - 我使用尾随的`=`使得像%= ExitCode =%这样的东西是"注释"而不是动态变量.我更喜欢使用一种始终有效的风格(除了当然在答案底部注明的限制). (3认同)

Jam*_*s K 25

在我意识到我可以使用标签::来发表评论和评论代码之后REM,我看起来很丑陋.正如所提到的内部使用时,双冒号可能会导致问题()受阻代码,但我已经通过标签之间交替发现了一个变通:::space

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

(
  :: But
   : neither
  :: does
   : this.
)
Run Code Online (Sandbox Code Playgroud)

它并不丑陋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
.
.
.
Run Code Online (Sandbox Code Playgroud)

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

  • 插入或删除行时,交替的单冒号和双冒号一定很头疼. (16认同)

mkl*_*nt0 20

这个答案尝试在这个页面上的许多伟大答案的实用总结:

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


全行注释 - 唯一直接支持的样式:

  • REM(或其案例变体)是唯一的官方评论构造,并且是最安全的选择 - 请参阅Joey的有用答案.

  • ::是一种(广泛使用的)hack,它有利有弊:


如果你希望使用::,您有以下选择:

  • 无论是:为了安全起见,让里面的异常(...)块,并使用REM有,或执行不到位的意见里面 (...)完全.
  • 或者:记住内部安全使用::(...)痛苦限制性规则,这些规则在以下片段中进行了总结:
@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.
)
Run Code Online (Sandbox Code Playgroud)

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

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


内联评论:

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

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

  • EOL评论([to-the-] end-of-line),可以放在命令之后,并且总是延伸到行尾(再次,由jeb的答案提供):

    • ver & REM <comment>利用REM有效命令的事实,&可用于在现有命令之后放置附加命令.
    • ver & :: <comment>也适用,但实际上只能在(...)块之外使用,因为它的安全使用比使用::独立更加有限.
  • 行内注释,放在一行上的多个命令之间,或理想情况下放在给定命令的内部.
    行内注释是最灵活的(单行)形式,并且根据定义也可以用作EOL注释.

    • ver & REM^. ^<comment^> & ver允许在命令之间插入注释(再次,由jeb的答案提供),但请注意如何<>需要被^释放,因为以下的字符.不能原样使用:(< > |而非转义&&&||启动下一个命令).

    • %= <comment> =%,在详细dbenham最伟大的答案,是最灵活的形式,因为它可以放在里面的命令(参数中).
      它以一种确保表达式总是扩展为空字符串的方式利用变量扩展语法- 只要注释文本既不包含%也不包含:
      Like REM,就%= <comment> =%可以很好地适用于外部和内部(...)块,但它在视觉上更加独特; 唯一的缺点是键入更难,语法更容易出错,而且不广为人知,这可能会妨碍对使用该技术的源代码的理解.


多行(整线)评论:

  • James K的答案显示了如何使用goto语句和标签来界定任意长度和内容的多行注释(在他的情况下,他用来存储使用信息).

  • Zee的答案显示了如何使用"空标签"来创建多行注释,但必须小心终止所有内部线条^.

  • Rob van der Woude的博客文章提到了另一个有点模糊的选项,它允许你以任意数量的注释行结束一个文件:一个开头(只会导致之后的所有内容被忽略,只要它不包含(非)^-escaped)),即只要块未关闭.


[1]使用SET "foo=bar"以定义变量-即把双引号的名称和=与该值组合 -是在诸如命令必要SET "foo=bar" & REM Set foo to bar.,以确保什么如下预期的变量的值(到下一个命令,在这种情况下一个空间)不会意外地成为它的一部分.
(顺便说一句:SET foo="bar"不仅不会避免问题,它会使双引号成为值的一部分).
请注意,此问题是固有的SET,甚至适用于值后面的意外尾随空格,因此建议始终使用该SET "foo=bar"方法.


mis*_*153 7

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

  • 这是事实,至少对于Win7SP1,`::`可以比`REM`快6倍 (2认同)

归档时间:

查看次数:

319387 次

最近记录:

7 年,6 月 前