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

[原创] [教程汇总]批处理中预处理机制及其应用

批处理脚本高级编程技巧——变量嵌套以及预处理的优先级
http://bbs.bathome.net/thread-6537-1-1.html

预处理、变量延迟、call引出的一些问题
http://bbs.bathome.net/thread-3349-1-1.html

只用一句话能set并输出吗?
http://bbs.bathome.net/thread-1100-1-1.html

批处理常见问题解答
http://bbs.bathome.net/thread-1200-1-1.html

在变量延迟打开的情况下如何输出感叹号
http://bbs.bathome.net/thread-1962-1-1.html
  1. 预处理时对百分号%的一种处理机制
  2. 原文地址:http://bbs.verybat.org/viewthread.php?tid=10907
  3. 问题来源于我给别人写的一段代码,目的是过滤掉广告信息:
  4. @echo off&setlocal EnableDelayedExpansion
  5. for /r C:\ebook %%f in (*.txt) do (
  6.     for /f "usebackq delims=" %%i in ("%%f") do (
  7.         set "l=%%i"
  8.         set "l=!l:┌─────────────────────┐=!"
  9.         set "l=!l:│搜刮言情、玄幻小说!欢迎您来推荐小说      │=!"
  10.         set "l=!l:├─────────────────────┤=!"
  11.         set "l=!l:│更多小说下载                              │=!"
  12.         set "l=!l:│小说分享阅读,独乐乐不如众乐乐            │=!"
  13.         set "l=!l:┖─────────────────────┘=!"
  14.         echo.!l!>>"%%~nf.new.txt"
  15.     )
  16. )
  17. 有一文件C:\ebook\eg.txt内容如下:
  18. 引用:
  19. ……
  20. 师太,你竟敢跟贫道抢秃驴!
  21. (end)
  22. ┌─────────────────────┐
  23. │搜刮言情、玄幻小说!欢迎您来推荐小说      │
  24. ├─────────────────────┤
  25. │更多小说下载                              │
  26. ├─────────────────────┤
  27. │小说分享阅读,独乐乐不如众乐乐            │
  28. ┖─────────────────────┘
  29. 结果输出为
  30. 引用:
  31. ……
  32. 师太,你竟敢跟贫道抢秃驴!
  33. (end)
  34. │搜刮言情、玄幻小说!欢迎您来推荐小说      │=
  35. ├─────────────────────┤=
  36. │更多小说下载                              │=
  37. │小说分享阅读,独乐乐不如众乐乐            │=
  38. │更多小说下载                              │=
  39. ┖─────────────────────┘=
  40. 问题大致是:上一行被替换成下一行内容,且后面多了“=”。并没有达到预想的目的。
  41. 仔细思考一下可以找到原因:
  42. 以l=┌─────────────────────┐为例,经过第一次替换,变量l被清空(实际上变量名被取消定义,可以用if defined l检测◎)。
  43. 现在问题来了:在第二次替换时,即set "l=!l:│搜刮言情、玄幻小说!欢迎您来推荐小说      │=!",既然l已经不是变量,就应该被当作普通字符,而在预处理时,特殊字符!被消去,那么此时l的值应该为l:│搜刮言情、玄幻小说!欢迎您来推荐小说      │=,但l:为何不见了呢?
  44. 先看分析时用到的一个例子:
  45. @echo off
  46. set aaa=10
  47. echo %aaa:~1
  48. echo %aaa~1
  49. echo.
  50. echo %bbb:~1
  51. echo %bbb~1
  52. set aaa=
  53. echo.
  54. echo %aaa:~1
  55. echo %aaa~1
  56. echo.
  57. set bbb=20
  58. echo %bbb:~1
  59. echo %bbb~1
  60. pause
  61. 运行结果为
  62. 引用:
  63. aaa:~1
  64. aaa~1
  65. ~1
  66. bbb~1
  67. ~1
  68. aaa~1
  69. bbb:~1
  70. bbb~1
  71. 请按任意键继续. . .
  72. 看出什么不同了吗?
  73. 开始设置aaa为变量,而未设bbb,结果echo %aaa:~1的输出为aaa:~1,而echo %bbb:~1的输出为~1,字符“bbb:”直接被消去。接着取消变量aaa,结果echo %aaa:~1的输出也变成~1,字符“aaa:”也直接被消去。再接着设bbb为变量,结果echo %bbb:~1的输出变成bbb:~1,字符“bbb:”又回来了。而不管aaa、bbb是否为变量,%aaa~1、%bbb~1的输出不变。
  74. 从中可以看出预处理时对百分号%的一种处理机制:首先是百分号%被消去①,然后看%后面的字符之后有无冒号“:”,如果没有,%后面的字符被保留。如果有冒号“:”,则看%与冒号“:”之间的字符是否为已经定义的变量名,如果是变量名,则此变量名与冒号“:”都会被保留;如果不是,则%与冒号“:”之间的字符包括冒号“:”都被消去,只保留冒号“:”之后的字符。
  75. 在开启变量延迟的情况下,是用!代替%,预处理时对其处理方式与%相同。
  76. 知道这个处理机制后,就不难解释文章开关提到的问题了。
复制代码
1

评分人数

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

无聊路过,顶一下,一篇不错的文章,就是看的人少的点

TOP

预处理机制 要好好研究下

TOP

回复 1# Batcher


      例子简单,解释明了,很好。不过冒号 :在这里到底扮演了什么角色还是没有说清楚。
      通常,两个变量符号(%和!)之间的变量名会被替换成变量名所指向的命令和字符,此时,变量符号和变量名都会被隐藏掉,而被变量指向的内容则呈现到屏幕上,如果内容不存在,则不显示,同时也不会回显,但不知道有没有返回码。按常见的模式看,变量符号一般是指%和!但这里的冒号似乎也有充当了类似的功能,在与!和%配对时,它也能把两者之间的字符消掉。冒号在其他地方的作用还有标签名、SET截取替换等如果是界定标签名,在句子中也用不着放标签,如果是替换,那如果把%var:~1,1%中冒号前面的var去掉了,留下的~1,1又做何用?为什么要用多一个“~”……百思不得其姐!~
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

好帖,不过例子中的去除广告的问题究竟该如何解决呢?

TOP

从另一个帖子转过来的,同样的一条命令,在后开启了变量延迟的情况下,输出正确的结果;
但在未开启变量延迟的情况下,报错,这就是预处理吗?
  1. set "var=|"
  2. echo %var%
  3. pause
复制代码
再如下:
  1. set "var=|"
  2. setlocal enabledelayedexpansion
  3. echo %var%
  4. pause
复制代码
例1在第一行添加 %1 cmd /k %0 : 可以看到报错信息。
同样的一条set "var=|" 命令,却有两条不同的结果,这个结果是由后面的代码所决定的。
预处理 = = ,解释器先扫描整个批处理脚本,如果发现语法错误,便提示报错,或者退出批处理脚本,如果一切正常,那便自上而下,逐条执行。
但预处理应该不是自上而下的,而是对当前脚本代码进行的综合分析。
踏实一些点.不要着急.你想要的时间都会给你.2

TOP

我刚刚用setlocal abledelayedexpansion来延迟变量,也可以额

TOP

说得很有道理支持!!

TOP

本帖最后由 wxyz0001 于 2019-11-8 00:01 编辑

预处理机制的问题,可以把下面这个for循环的例子来讲述一下特殊字符的优先级
for /f "tokens=1,2" %%i in ('ipconfig /all^|find /i "Physical Address"') do set mac=%%i
当for循环的集合中两个命令间的管道符没有用^来转义成普通字符,当DOS读到这条语句后会用|管道符切割成两半,
一半是
for /f "tokens=1,2" %%i in ('ipconfig /all,
另一半是
find /i "Physical Address"')
而显然for /f "tokens=1,2" %%i in ('ipconfig /all这样的代码DOS是处理不了的。
当for循环集合中的管道符用^转义成普通字符,()括号中的代码才能成为一行语句,才能让for处理。
其他的& && || > >>同样道理。

TOP

返回列表