我正在尝试使用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 link:rem
),我对适用于Windows的解决方案感兴趣Vista,Windows 7或更高版本。
答案 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.bat
,REM;.bat
等等。)
在REM^<char>
之后添加空格总是一个好主意。
%~
的问题无法解决,因为cmd.exe为每一行使用多个解析器阶段。
并且在早期阶段(百分比扩展阶段)检测到%~
错误,就在检测到REM
的阶段之前。
但是,根据dbenham描述的内联评论,我会优先考虑百分之百的评论
修改强>
我从REM^<char>
删除了插入符号,因为它没关系。
正常情况下,REM
会对该行的其余部分进行备注,因为批处理解析器会在解析器的phase2中检测到REM
关键字,并仅针对REM切换到专用解析器。
但是当一个字符被追加到REM
时,该关键字将不会在第二阶段被检测到
如果该字符是\/;,=+(
之一,则解析器将在以后删除它并执行正常 REM命令。
这就是为什么在这种情况下可以识别命令运算符&
,&&
,|
,||
的原因。
为什么rem/ | break
失败,但(REM/) | break
有效?
这是因为管道启动了两个单独的cmd子进程
使用周围的括号,将在子进程中第一次解析该命令
但是没有括号,父进程已经解析了REM/
并检查文件是否存在(但是没有执行)。
但是当这样的文件存在时,解析器就足够聪明,可以删除分隔符并检测到REM
是一个内部命令。
这种行为看起来有点奇怪。