如何在不忽略相邻命令的情况下在命令行中可靠地使用`rem`?

时间:2016-01-14 01:53:53

标签: windows batch-file cmd comments

我正在尝试使用rem命令在包含多个命令的命令行中添加注释。以下是一些例子来说明我的意思:

echo Hello & rem.Comment & echo world!

(echo Hello & rem.Comment) & echo world!

这完全正常,每行中的echo个命令都按照我的预期执行。 .似乎修改了rem命令的行为,因此它不会将剩余行视为注释:

Hello 
world!

如果我放置 SPACE (或任何其他分隔符 TAB ,;=)而不是.,其余行以及第二个echo将被忽略(对于第二个示例,会出现More?提示,因为)是评论的一部分而cmd由于)):

,我希望收到(
Hello 

我发现在.旁边,以下字符也有效::/\[]+ 还有什么可用的是转义分隔符:^ SPACE ^ TAB ^,^;和{{1 }}。

然而,有一种安全可靠的方式吗?

对于适用于命令提示符和批处理文件的解决方案,我感到非常高兴。

根据this external reference,在某些情况下,用于返回空行的熟悉语法^=会失败,因此建议使用echo.,因为这是唯一可靠的方法。

但是,对于echo(rem不起作用,(之后的所有内容都无法识别为命令。

由于我知道Windows XP中rem(命令的一个奇怪错误(参考this external linkrem),我对适用于Windows的解决方案感兴趣Vista,Windows 7或更高版本。

2 个答案:

答案 0 :(得分:7)

"怪异的" REM %~" bug"不仅限于XP。它存在于使用CMD.EXE的所有Windows现代版本中。在阅读完您的问题后,我wrote Simon of SS64 a note就此问题做了澄清。如果存在变量 var ,则REM也会失败,并且您有rem %var:=

从技术上讲,无法保证盲目使用REM的安全方式。

但是,如果您愿意接受致命的%扩展风险,那么您列出的大多数黑客都可以安全使用,但如果该行包含至少一个来自{{1}的附加命令, }或&

如果存在名为&&的文件(没有扩展名),

REM.在任何情况下都无法安全使用。

如果当前文件夹包含名为REM的文件且您使用\,文件夹分隔符/test.bat将始终失败。

以类似的方式,REM\..\test.bat总是失败。

在类似的情况下,其他每一个黑客都可以单独失败。例如,REM:\..\test.bat单独失败,但如果与另一个命令连接则有效。这是我发现REM^[tab]\..\test.bat+[]失败的唯一情况。

还有一些其他案例可能会失败。

在文件名中有效的集合C(^[tab]^[space]^,^;)中的任何字符都可以独立失败{{1}存在。例如,以下内容无法独立:

^=

然而,当与另一个命令连接时,它们都是安全的:

remC.bat

临时更新

以上一些是错误的。调查正在http://www.dostips.com/forum/viewtopic.php?f=3&t=6895&p=44813#p44813进行。

我相信以下是最简单的形式,保证在所有情况下都有效(忽略无效的%扩展)

rem^  Fails if "rem .bat" exists

但是,在尘埃落定之前,我不会纠正早期的信息

结束临时更新


我最喜欢使用内联注释的方法是使用不可能的变量。只有动态伪变量可以在名称中包含echo OK&rem^ This is safe rem^ This is safe &echo OK ,并且任何变量名称都不能包含两个REM: At least one space (or other token delimiter) must be after : REM\ At least one space (or other token delimiter) must be after \ REM/ At least one space (or other token delimiter) must be after / REM^[tab] At lease one space (or other token delimiter) must be after [tab] 。所以我喜欢使用=。只要评论不包含=%= Remark goes here =%,这种形式的美妙之处在于它可以在任何地方使用,而且不受惩罚。它甚至可以在带括号的代码块中安全使用。

%

答案 1 :(得分:3)

这种REM变体似乎是一种在注释部分启用&符号的安全方法。

REM/
REM\
REM:

尽管有@ dbenham的评论,我无法创建任何与这些REM变体相符的文件(我尝试REM.batREM;.bat等等。) 在REM^<char>之后添加空格总是一个好主意。

%~的问题无法解决,因为cmd.exe为每一行使用多个解析器阶段。
并且在早期阶段(百分比扩展阶段)检测到%~错误,就在检测到REM的阶段之前。

但是,根据dbenham描述的内联评论,我会优先考虑百分之百的评论

修改
我从REM^<char>删除了插入符号,因为它没关系。

正常情况下,REM会对该行的其余部分进行备注,因为批处理解析器会在解析器的phase2中检测到REM关键字,并仅针对REM切换到专用解析器。

但是当一个字符被追加到REM时,该关键字将不会在第二阶段被检测到 如果该字符是\/;,=+(之一,则解析器将在以后删除它并执行正常 REM命令。

这就是为什么在这种情况下可以识别命令运算符&&&|||的原因。

为什么rem/ | break失败,但(REM/) | break有效? 这是因为管道启动了两个单独的cmd子进程 使用周围的括号,将在子进程中第一次解析该命令 但是没有括号,父进程已经解析了REM/并检查文件是否存在(但是没有执行)。
但是当这样的文件存在时,解析器就足够聪明,可以删除分隔符并检测到REM是一个内部命令。
这种行为看起来有点奇怪。