[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[代码合集] 【已解决】echo显示^和%及其他字母组合时致使怪异显示结果

先看代码:
1.
  1. @echo off
  2. echo %num%
  3. pause
复制代码
2.
  1. @echo off
  2. echo ^^num^^
  3. pause
复制代码
3.
  1. @echo off
  2. echo %%num%%
  3. pause
复制代码
4.
  1. @echo off
  2. echo %%num^^
  3. pause
复制代码
5.
  1. @echo off
  2. echo ^%num^^
  3. pause
复制代码
6.
  1. @echo off
  2. echo ^%num^%
  3. pause
复制代码
上面六段代码显示效果都不一样。1因为num未定义显示echo的关闭状态,好理解,2、3、4因为变量两边的特殊字符的第一个都用作转义,也好理解。问题是5、6段代码,5显示结果为“num^”,为什么前面的^%就没有任何显示呢?我试过如果将代码5的echo ^%num^^改成echo ^%的话,运行以后窗口一闪就没了,为什么会这样呢?至于代码6,也是运行以后窗口一闪就没了。麻烦论坛的达人给解释一下,多谢。


经论坛各位达人指教后得出结论,整理如下:
1、^身兼两重重任:当它不位于行尾的时候,它起到转义字符的作用,也就是取消紧跟在它之后的那个字符的特殊用法,化特殊字符为普通字符,比如|、>、&,在转义的时候,它本身也会消失,而不论是否对后面的字符做了转义,所以如果要显示^本身的时候,需要写成 echo ^^ ;当它位于命令行的尾部时,它将起到连字符的作用,也就是把下一行的字符与它所在的那一行相连,视为同一行处理,就像随风在2楼所举例的那样;
2、%也扮演双重角色——转义%或引用变量:如果要在命令行中显示%本身的话,需要用连续两个百分号来表示,写成 echo %%;单独的%会被认为在做变量引用,在预处理阶段的时候,CMD.EXE解释器会对单独的百分号做表分号对匹配,搜索是否有在同一行上的另外一个百分号和它配对,如果有的话,就认为是在做变量引用,如果没有的话,这个百分号将会被丢弃,所以,echo ^%num^^ 的结果是显示 num^;
3、CMD.EXE在做预处理的时候,如果^和%同时存在,将先做%的变量引用匹配,再对引用结果做^转义,也就是说,%的优先级高于^;
综合以上三点,当 echo ^%num^% 的时候,先对百分号对里的变量做引用,因为 num^ 这个变量没有被定义,所以值为空,echo ^%num^% 也就相当于执行了 echo ^ 这个命令;又因为此时 ^ 已经位于行尾,所以,它不是起转义字符的作用,而是起连接上下两行的连字符作用,在执行第6个代码的时候,整个代码的意思就是在 echo pause ,此时的 pause 是 echo 的对象,而不是单独的一条命令,在第6个代码的下一行再加一条 pause 语句就可以看出来了。

另外,在两个各百分号之间的的特殊字符不会当作特殊字符处理,而是当作组成变量名的普通字符来处理,如:
  1. @echo off
  2. set num^^=2009
  3. set num=09
  4. echo ^%num^^%
  5. pause
  6. pause
复制代码
显示结果为pause。
所以要显示变量num^^的值,必须在%%之间写成num^。上段代码因为中间写了两个^致使num^^被识别为未定义字符,故echo ^%num^^%被解释成echo ^,^做连字符处理连接pause。

至此,水落石出,尘埃落定。多谢所有前辈指点迷津。
新手也不用逐楼攀爬了。
无量公德……

[ 本帖最后由 Lumiere 于 2009-3-24 10:36 编辑 ]
1

评分人数

    • Batcher: 感谢主动给标题标注[已解决]字样PB + 2

原帖由 Lumiere 于 2009-3-23 17:34 发表
我试过如果将代码5的echo ^%num^^改成echo ^%的话,运行以后窗口一闪就没了,为什么会这样呢?至

因为最后一个 ^ 起到了连接下一行的作用,变成了 echo ^%pause
你再加一个pause就明白了
:
  1. @echo off
  2. echo ^%
  3. pause
  4. pause
复制代码

[ 本帖最后由 随风 于 2009-3-23 18:05 编辑 ]
技术问题请到论坛发帖求助!

TOP

  1、^身兼两重重任:当它不位于行尾的时候,它起到转义字符的作用,也就是取消紧跟在它之后的那个字符的特殊用法,化特殊字符为普通字符,比如|、>、&,在转义的时候,它本身也会消失,而不论是否对后面的字符做了转义,所以如果要显示^本身的时候,需要写成 echo ;当它位于命令行的尾部时,它将起到连字符的作用,也就是把下一行的字符与它所在的那一行相连,视为同一行处理,就像随风在2楼所举例的那样;
  2、%也扮演双重角色——转义%或引用变量:如果要在命令行中显示%本身的话,需要用连续两个百分号来表示,写成 echo %%;单独的%会被认为在做变量引用,在预处理阶段的时候,CMD.EXE解释器会对单独的百分号做表分号对匹配,搜索是否有在同一行上的另外一个百分号和它配对,如果有的话,就认为是在做变量引用,如果没有的话,这个百分号将会被丢弃,所以,echo ^%num^^ 的结果是显示 num^;
  3、CMD.EXE在做预处理的时候,如果^和%同时存在,将先做%的变量引用匹配,再对引用结果做^转义,也就是说,%的优先级高于^;
  
  综合以上三点,当 echo ^%num^% 的时候,先对百分号对里的变量做引用,因为 num^ 这个变量没有被定义,所以值为空,echo ^%num^% 也就相当于执行了 echo ^ 这天命令;又因为此时 ^ 已经位于行尾,所以,它不是起转义字符的作用,而是起连接上下两行的连字符作用,在执行第6个代码的时候,整个代码的意思就是在 echo pause ,此时的 pause 是 echo 的对象,而不是单独的一条命令,在第6个代码的下一行再加一条 pause 语句就可以看出来了。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

^是转义字符,而不是逃逸字符吧?逃逸字符是%啊。楼上笔误?
^在不在行尾都一样吧?在行尾的时候它就是把回车换行给转义了,跟不在行尾的时候道理相同。
1

评分人数

    • namejm: 呵呵,一针见血地揭露了本质的东西。PB + 2
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

  呵呵,确实是我糊涂了,这就改。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

回复三楼

多谢namejm的讲解,感觉醍醐灌顶。不过还有两个小地方需要你再讲解下。
你写出的三点加综合,基本理解了,第一点没问题,第二点,echo ^%num^^ 的结果是显示 num^,照你的解释的话,其中的三个^第一个不在行尾,那它就没当做连字符,那作用应该是转义,当作为转义符的时候他后面无论跟什么字母是不是都只显示它后面的字符,自己就消失了?那它到底起了转义的作用没有?
再就是最后的综合段落,echo ^%num^% ,首先配对百分号变量引用,如果是这样一个步骤的话num^应该被系统识别为非法字符串才对啊,因为里面的num^其中的^字符没有做转义处理,应该首先就识别它有语法错误,不会进行接下来的步骤将echo ^%num^% 解释成echo ^。不知道我这么想对不对。麻烦你不好意思,还请赐教。

TOP

回复 4楼 的帖子

Batcher,本来已经比较豁然开朗了,被你一讲我又糊涂了,namejm说的错了么?什么是逃逸字符?怎么又给回车转义了?是不是什么字符都可以转义的?

TOP

原帖由 Batcher 于 2009-3-23 20:02 发表
^在不在行尾都一样吧?在行尾的时候它就是把回车换行给转义了,跟不在行尾的时候道理相同。

  呵呵,这个话说到了本质,而我的理解还停留在表面——大部分时候,我都是凭自己的反复测试得出感性的经验之谈而不求甚解,往往深入不了问题的实质。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

回复 7楼 的帖子

3楼在刚开始回复的时候由于笔误写错了一个名词,现在已经更正了,你按照3楼的讲解来掌握即可。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

原帖由 Lumiere 于 2009-3-23 20:36 发表
第二点,echo ^%num^^ 的结果是显示 num^,照你的解释的话,其中的三个^第一个不在行尾,那它就没当做连字符,那作用应该是转义,当作为转义符的时候他后面无论跟什么字母是不是都只显示它后面的字符,自己就消失了?那它到底起了转义的作用没有?
再就是最后的综合段落,echo ^%num^% ,首先配对百分号变量引用,如果是这样一个步骤的话num^应该被系统识别为非法字符串才对啊,因为里面的num^其中的^字符没有做转义处理,应该首先就识别它有语法错误,不会进行接下来的步骤将echo ^%num^% 解释成echo ^。

  1、^在转义的时候,它本身是要消失掉的,而无论它后面紧跟的是不是特殊字符——如果是普通字符,因为它本身不具备任何特殊含义,^转义之后还是字符本身;如果^后紧跟的是一个特殊字符,它被^转义之后,特殊用法就消失了,它将转化为字符本身,从而成为一个普通字符,例如: echo ^|^a,执行的结果将显示 |a ——在这里,| 是特殊字符,起管道作用,但是被转义之后,它就只是一个字符 | 而已,不再具备管道的作用,a本身就是一个普通字符,被转义之后,它仍然是普通字符,在这条语句中,^都起到了转义的作用,转义完成之后,^本身也要随之消失;
  2、echo ^%num^% 的时候,先匹配百分号对,被识别为是在做变量引用,引用的变量是 num^ ;但是,这里的 ^ 它本身是转义字符,从而 num^ 将转化为 num ——也就是在说,在做变量引用的时候,变量名先被识别为 num^,进而又被识别为 num。做完变量引用的工作之后,语句将变成 "echo ^空值" 的格式,空值是不占用任何存储空间的,这条语句就相当于 echo ^ 了,这个时候,开始做^转义,^转义的是行尾的回车换行符号(回车换行符号为不可见字符,人眼不可见,但机器可识别),这个时候,它就起到了上下行连字符的作用。呵呵,因为我也是在凭自己的经验在做推理,没有权威理论的支持,这个过程可能比较难以理解,希望其他人能从批处理的预处理机制这个高度上做一下解释。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

关于楼主所说的“运行以后窗口一闪就没了”,我这里给个建议吧,如果对批处理感兴趣,就该学会如何调试批处理。
不要双击运行,在命令行解释器中运行吧,遇到不明白的地方,就把@echo off删除,仔细看看看看执行过程,就容易理解些。

开始
运行
cmd
test.bat
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 10楼 的帖子

我来说说预处理吧:
@echo off
echo ^%num^%
pause
预处理时,先进行变量扩展,但是命令行解释器发现变量%num^%未被定义,于是把它替换为空,代码变成了:
@echo off
echo ^
pause
这个尖括号把第二行行尾的回车换行给转义了,于是代码等效于:
@echo off
echo pause
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 12楼 的帖子

那是不是和win下回车是"0d0a"有关?

TOP

回复 13楼 的帖子

确切的说,0D是回车,0A是换行。
但是甭管它是啥,知道^把它转义了即可。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 14楼 的帖子

有空试试拿*nix下的回车来看看有什么效果

TOP

返回列表