标题: [其他] [已解决]关于批处理BAT换行符的疑问 [打印本页]
作者: zhanglei1371 时间: 2014-4-10 23:29 标题: [已解决]关于批处理BAT换行符的疑问
本帖最后由 zhanglei1371 于 2014-4-11 14:16 编辑
问题从这两个帖子说起:
"【分享】批处理不启用变量延迟的情况下输出换行符(0A)"http://bbs.bathome.net/viewthread.php?tid=20262
和" 批处理技术内幕:预处理"http://bbs.bathome.net/viewthrea ... =%D4%A4%B4%A6%C0%ED
第一种- @echo off
-
- :: ---------------- 获取换行符 0A ---------------------
- set NLM=^
-
-
- set NL=^^^%NLM%%NLM%^%NLM%%NLM%
- :: ---------------- /获取换行符 0A ---------------------
-
- echo a%NL%b
-
- pause
复制代码
第二种- @echo off
- set "n=&echo;"
- echo a%n%b
- pause
复制代码
而Batcher却说第二种是0D0A,第一种为0A,这里何解?
apang的一些解释:
如果要从字串 ab 中间换行,分成两行显示,可以这样:- @echo off
- echo,a^
-
- b
- pause
复制代码
批处理内幕:^后面是三个0x0A(换行符\n的十六进制,0x0D会被丢弃掉,故不考虑它),第一个0x0A会被丢弃掉,第二个0x0A会被当成set命令参数的一部分,而第三个0x0A是分隔符,表示命令结束。所以CMD最终运行的命令是set lf=[0x0A](换行符看不见,只好这样表示。)
那么,再用set 时,为何是两个空行,而echo时只用一个空行?
另外,在开启变量延迟时,有!!号括住时,又该是几个空行呢?
【最上面的二次转义我基本理解了,但是就是echo 1个空行的地方不太理解,为何不是set的两个】
作者: Demon 时间: 2014-4-11 00:28
难得还有人学习批处理,简单回答一下吧。- @echo off
- set "n=&echo;"
- echo a%n%b
- pause
复制代码
相当于- @echo off
- echo a
- echo;b
- pause
复制代码
当然是0D0A
作者: Demon 时间: 2014-4-11 00:35
至于一个空行还是两个空行的问题,把代码改一下你可能就明白了。- @echo off
- echo,a^
-
-
- b
- pause
复制代码
输出- a
-
- 'b' 不是内部或外部命令,也不是可运行的程序
- 或批处理文件。
- 请按任意键继续. . .
复制代码
多一个空行就多一个0x0A,而0x0A属于批处理中的分隔符,所以把命令截断了,于是CMD在解析时认为b是一条命令,但是找不到该命令,故报错“'b' 不是内部或外部命令,也不是可运行的程序”。而截断命令是在set中我们要追求的结果,所以要用两个空行。
作者: CrLf 时间: 2014-4-11 03:52
补充一句,对 % 的解析发生在语法解释之前
其余同上
有兴趣的话,往这看:
http://bbs.bathome.net/viewthread.php?tid=6692
http://bbs.bathome.net/viewthread.php?tid=18351
http://bbs.bathome.net/viewthread.php?tid=12891
作者: zhanglei1371 时间: 2014-4-11 09:26
回复 3# Demon
谢谢,两行和1行的问题,我知道了。但是第一个0D0a的地方还是不知怎么回事。二楼的解释我之前也知道是这么回事,因为都是这样分成两行,但是分成两行后怎么知道其后面的是回车+换行符,而复制代码
中的却是换行,而不是回车+换行?
我的理解:是否只要在set中,^号后面假如有回车+换行符时,就如预处理文章中所说的那样,回车就直接被舍弃掉了,仅剩下换行符,因此,此时不涉及回车符,仅有换行符在进行操作?
不知这样理解是否正确,还望明示。
作者: Demon 时间: 2014-4-11 12:45
echo命令输出字符的时候会在后面自动加上0D0A,这应该是常识吧。- @echo off
- (echo a
- echo;b)>1.txt
- (echo a^
-
- b)>2.txt
- pause
复制代码
用十六进制编辑器打开1.txt和2.txt,内容分别是
61 0D 0A 62 0D 0A
61 0A 62 0D 0A
你的理解并不正确,批处理在进行词法分析的时候是会忽略掉0x0D的,与命令无关。
作者: zhanglei1371 时间: 2014-4-11 14:15
回复 6# Demon
多谢指点,基本明白些了。现将开头的获取0A的部分解释下,有不对的地方,还请批评指正!- :: ---------------- 获取换行符 0A ---------------------
- set NLM=^
-
-
- ::这里NLM已经是一个换行符了,可以用echo a!NLM!b查看效果,但是%NLM%却仍为空【不知为何】。
- set NL=^^^%NLM%%NLM%^%NLM%%NLM%
- ::这里这样理解:先替换%%中的东西:变成(^^)(^换行符换行符)(^换行符换行符)[其实上面的NLM就是1个换行符,加括号方便说明]
- ::经过预处理,变成:(^)(换行符)(换行符),到这里恰好和上面set NLM=的内容相一致
- :: ---------------- /获取换行符 0A ---------------------
-
- echo a%NL%b
- ::这里先替换:变成a(^)(换行符)(换行符)b,预处理一次:将第一个换行符干掉,留下第二个。就是最终结果了。
- pause
- REM ========代码区===========================
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |