[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]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
天的白色影子

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

TOP

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

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

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

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

本帖最后由 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

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

回复 13# amwfjhh


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

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

TOP

把以前的老帖翻出来炒冷饭
  1. :: 句柄模拟.cmd - 模拟运算句柄操作后的句柄状态
  2. :: qzwqzw - 2009-6-12
  3. @echo off & setlocal EnableDelayedExpansion
  4. if [%1]==[] (
  5.     echo. 这是句柄操作示例, 模拟运算进行几次句柄操作后的句柄状态
  6.     echo --------------------- call %~n0 ">nul" "2>nul" ---------------------
  7.     call %0 ">nul" "2>nul"  
  8.     set 句柄
  9.     echo.
  10.     echo --------------------- call %~n0 ">nul" "2>nul" "3>nul" ---------------------
  11.     call %0 ">nul" "2>nul" "3>nul"  
  12.     set 句柄
  13.     echo.
  14.     echo --------------------- call %~n0 ">nul" "2>&1" "3>&1" ---------------------
  15.     call %0 ">nul" "2>&1" "3>&1"  
  16.     set 句柄
  17.     echo.
  18.     echo --------------------- call %~n0 ">nul" "3>nul" "4>nul" ---------------------
  19.     call %0 ">nul" "3>nul" "4>nul"  
  20.     set 句柄
  21.     echo.
  22.     echo --------------------- call %~n0 "3>nul" "4>nul" ---------------------
  23.     call %0 "3>nul" "4>nul"  
  24.     set 句柄
  25.     echo.
  26.     pause
  27.     goto :eof
  28. )
  29. set "0=con" & set "1=con" & set "2=con"
  30. for %%h in (%句柄%) do set %%h
  31. echo.----- 起始状态 Initiation state -----
  32. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  33. echo.
  34. echo.----- 预处理 Pre-process -----
  35. :loop
  36. if [%1]==[] goto :end
  37. echo.----- %1 -------
  38. set "_tmp=%~1"
  39. if "%_tmp:~0,1%"=="<" set "_tmp=0%_tmp%"
  40. if "%_tmp:~0,1%"==">" set "_tmp=1%_tmp%"
  41. set _句柄=%_tmp:~0,1%
  42. set _句柄_2=
  43. set _dev=
  44. if "%_tmp:~2,1%"=="&" (set _句柄_2=%_tmp:~3%) else (set _dev=%_tmp:~2%)
  45. for %%h in (0 1 2 3 4 5 6 7 8 9) do (
  46.     if "!%%h!"=="" (
  47.         set/p=b: %_句柄%[!%_句柄%!]=^>%%h[!%%h!] : <nul
  48.         set "%%h=!%_句柄%!"
  49.         set bak_%%h=%_句柄%
  50.         goto :set
  51.     )
  52. )
  53. :set
  54. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  55. echo.
  56. if defined _dev (
  57.     set/p=a: %_dev%=^>%_句柄%[!%_句柄%!] : <nul
  58.     set %_句柄%=%_dev%
  59. ) else if defined _句柄_2 (
  60.     set/p=a: %_句柄_2%[!%_句柄_2%!]=^>%_句柄%[!%_句柄%!] : <nul
  61.     set %_句柄%=!%_句柄_2%!
  62. )
  63. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  64. echo.
  65. shift
  66. goto :loop
  67. :end
  68. echo.----- 后处理 Post-process -----
  69. for %%h in (0 1 2 3 4 5 6 7 8 9) do (
  70.     if not "!bak_%%h!"=="" (
  71.         set/p=r: !bak_%%h![]^<=%%h[!%%h!] : <nul
  72.         set !bak_%%h!=!%%h!
  73.         set %%h=
  74.         set bak_%%h=
  75.         for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  76.         echo.
  77.     )
  78. )
  79. set 句柄=
  80. for %%h in (0 1 2 3 4 5 6 7 8 9) do set 句柄=!句柄! "%%h=!%%h!"
  81. endlocal & set 句柄=%句柄%
  82. echo.----- 结束状态 End Status -----
  83. for %%h in (%句柄%) do set/p=%%~h <nul
  84. echo.
复制代码
1

评分人数

    • CrLf: 先加分再研究~技术 + 1
天的白色影子

TOP

返回列表