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

[原创] 批处理命令连接符号优先级证明

  1. @echo off
  2. echo.
  3. echo.    已经确认命令连接符号优先级从低到高如下:
  4. echo.            ^&       命令分隔符
  5. echo.            ^|^|          逻辑或操作符
  6. echo.            ^&^&          逻辑与操作符
  7. echo.            ^|           管道操作符
  8. echo.            ^< ^> ^>^>      I/O重定向操作符
  9. echo.            ^(^)          命令分组
  10. echo.
  11. echo.证明过程如下:
  12. pause
  13. echo.
  14. echo.  首先应当公认^(和^)作为命令分组符号有最高的优先级,可以改变任意命令组的优先级
  15. echo.
  16. echo.  另外需要注意的是,命令连接符号的优先级与语句的执行顺序不是直接对应的
  17. echo.
  18. echo.  命令行中的语句仍然是先执行左侧,再执行右侧
  19. echo.
  20. echo.  命令连接符只影响左侧与右侧语句的分组过程,而不会使右侧语句先执行
  21. echo.
  22. pause
  23. cls
  24. echo on
  25. echo flag1 | echo flag2 > con
  26. echo flag1 | (echo flag2 > con)
  27. (echo flag1 | echo flag2) > con
  28. @echo off
  29. echo.
  30. echo.前两句输出效果相同,说明第二句的分组符号可以省略,证明 ^> 优先级大于 ^|
  31. pause
  32. cls
  33. echo on
  34. echo flag1 && echo flag2 | echo flag3
  35. echo flag1 && (echo flag2 | echo flag3)
  36. (echo flag1 && echo flag2) | echo flag3
  37. @echo off
  38. echo.
  39. echo.前两句输出效果相同,说明第二句的分组符号可以省略,证明 ^| 优先级大于 ^&^&
  40. pause
  41. cls
  42. echo on
  43. echo flag1 || echo flag2 && echo flag3
  44. echo flag1 || (echo flag2 && echo flag3)
  45. (echo flag1 || echo flag2) && echo flag3
  46. @echo off
  47. echo.
  48. echo.前两句输出效果相同,说明第二句的分组符号可以省略,证明 ^&^& 优先级大于 ^|^|
  49. pause
  50. cls
  51. echo on
  52. echo flag1 || echo flag2 & echo flag3
  53. (echo flag1 || echo flag2) & echo flag3
  54. echo flag1 || (echo flag2 & echo flag3)
  55. @echo off
  56. echo.
  57. echo.前两句输出效果相同,说明第二句的分组符号可以省略,证明 ^|^| 优先级大于 ^&
  58. pause
  59. cls
  60. echo.综合测试示例:
  61. echo.
  62. echo on
  63. echo flag1 & more flag2 || echo flag3 && echo flag4 | echo flag5 || echo flag6
  64. echo flag1 & ((more flag2 || (echo flag3 && (echo flag4 | echo flag5))) || echo flag6)
  65. (echo flag1 & (more flag2 || (echo flag3 && echo flag4) | echo flag5)) || echo flag6
  66. @echo off
  67. echo.
  68. echo.前两句输出效果相同,说明符合优先级和分组优先级相同,第三句是个反例
  69. pause
复制代码
2

评分人数

    • plp626: 有意思技术 + 1
    • CrLf: 感谢总结分享PB + 5 技术 + 1
天的白色影子

有意思,先支持一下!

TOP

本帖最后由 CrLf 于 2012-3-22 23:39 编辑
  1. (echo flag1 | echo flag2) > con
复制代码
什么情况,这句在我电脑上似乎也出现了内存泄露?win7 系统,求验证及解答
另外,我觉得楼主对重定向符的优先级验证不严谨吧,应该这样证明:
  1. set =|find /c "" 2>nul
  2. (set =|find /c "") 2>nul
  3. set = 2>nul|find /c ""
复制代码

TOP

本帖最后由 plp626 于 2012-3-23 08:53 编辑

回复 3# CrLf


    你的“内存泄露”显示的是?
我这里:
  1. flag2♪◙
复制代码
比较惊讶的是后面两个特殊字符到底是什么?

TOP

回复 4# plp626


    显示是这样的,多显示了两个没见过的字符。话说让我吃惊的是,执行到这里时居然惊动了 360:
   
    而我电脑上的 0x0~0xff 应显示为:
   
附件: 您需要登录才可以下载或查看附件。没有帐号?注册

TOP

实际上那两个字符就是你的ID的“原形”
用这种方法还能显示出0x08 0x09等字符
天的白色影子

TOP

版主再仔细推敲一下你的证明代码
我觉得逻辑上似也有问题

至于我的证明代码
一方面因为我是先通过其它方法确认了这个优先级
再去寻求从代码角度证明的
另一方面为了追求代码的优雅
设计上主要考虑了前后代码的连贯性
所以有些逻辑上的疏忽在所难免

当然重定向符号的细节还比较多
包括句柄复制符号也没有展开来
天的白色影子

TOP

本帖最后由 plp626 于 2012-3-23 14:16 编辑

这个副产品有意思。。。cmd的黑框显示的字符还真多。。。下次准备更新 ascii.cmd
  1. cmd/v
  2. call ascmap.cmd $
  3. (echo;|echo off)>con&echo !$:~0,70!
复制代码

TOP

本帖最后由 CrLf 于 2012-3-23 16:23 编辑

回复 6# qzwqzw


噢,果然如此,写成这样和 dir 的结果一比较就很明显了:
  1. (echo;|dir)>con
复制代码
但是不知为何会因为重定向而导致回车换行符显现真身呢?08、09 确实试出来了,但是不知其所以然
  1. (echo;|set /p= )>con
  2. rem 长串空格为一个 tab 制表符
复制代码

TOP

本帖最后由 qzwqzw 于 2014-11-27 10:52 编辑

现在基本可以确定
| 和>这些符号会影响cmd的控制台IO模式
而这些模式会影响等控制台标准IO函数的行为
主要包括ReadFile/ReadConsole,WriteFile/WriteConsole
3,8,9楼的代码
主要是因为ENABLE_PROCESSED_OUTPUT模式被置假
导致WriteFile/WriteConsole不再特殊处理屏幕缓冲区中的控制区字符

可用的模式共
  1. ENABLE_ECHO_INPUT                        0x0004
  2. ENABLE_EXTENDED_FLAGS                0x0080
  3. ENABLE_INSERT_MODE                        0x0020
  4. ENABLE_LINE_INPUT                        0x0002
  5. ENABLE_MOUSE_INPUT                        0x0010
  6. ENABLE_PROCESSED_INPUT                0x0001
  7. ENABLE_QUICK_EDIT_MODE                0x0040
  8. ENABLE_WINDOW_INPUT                        0x0008
  9.                         
  10. ENABLE_PROCESSED_OUTPUT                0x0001
  11. ENABLE_WRAP_AT_EOL_OUTPUT        0x0002
复制代码
参考链接
http://msdn.microsoft.com/en-us/library/ms686033(VS.85).aspx
天的白色影子

TOP

让我想起了批处理内幕:句柄 那篇帖子了,后面有一个句柄转换后把con重新指给1句柄的,那里面就出现了cls控制字符的显示,看来根源也在这里。

TOP

本帖最后由 qzwqzw 于 2014-11-28 17:44 编辑

回复 11# amwfjhh

    让我想起了批处理内幕:句柄 那篇帖子了,后面有一个句柄转换后把con重新指给1句柄的,那里面就出现了cls控制字符的显示,看来根源也在这里。


你说的应该是《重定向中的秘密(句柄备份)》的27楼的问题
http://www.bathome.net/redirect. ... 92&fromuid=3023

两个问题其实并非同源
那里的问题主要是因为con并非完全仿真的控制台
导致cls以及dir/p等命令识别出了这个特殊设备
所以在显示逻辑上做了例外处理
在真正的控制台上cls不会输出0x0c的字符

这里的问题主要是管道、重定向以及括号字符的联用
导致控制台的IO模式发生变化
最终忽略了缓冲区中控制字符的特殊处理

你可以注意到两个问题的命令行用法并不完全相同
echo.>con并不会输出0x0d 0x0a的图形字符
echo+0x0c(可以通过Ctrl-L输入)也不会执行清屏
天的白色影子

TOP

回复 12# qzwqzw


    (echo,|set a=&cls)>con

TOP

本帖最后由 qzwqzw 于 2014-11-28 17:54 编辑

回复 13# amwfjhh


    你想通过这段代码说明什么?

代码中>con会将标准输出重定向到con
而cls执行时会探测到标准输出不再是原来的控制台
因此直接输出字符了事
天的白色影子

TOP

话说句柄默认输出就是标准设备,那么可以这样:
  1. (cls 1>&2)>nul
  2. pause
  3. (cls 1>&3)>nul
  4. pause
复制代码
测试中从句柄 4 开始都不能放在 >& 之后,会报这个错误:
  1. 重定向句柄 N 时,
  2. 无法复制此句柄。
复制代码

TOP

返回列表