无忧启动论坛

标题: 请批处理高手帮我做一个文本中关于内容统计的批,谢! [打印本页]

作者: 老毛桃    时间: 2006-11-23 22:25
标题: 请批处理高手帮我做一个文本中关于内容统计的批,谢!
是这样的,我有一个记录文档,比如名称为 SearchNet.txt,里面内容如下:

  1. 5
  2. 7
  3. 15
  4. 18
  5. 29
  6. 34
  7. 45
  8. 50
  9. 53
  10. 55
  11. 57
  12. 61
  13. 64
  14. 70
  15. 71
  16. 75
  17. 81
  18. 86
  19. 87
  20. 89
  21. 98
  22. 99
  23. 103
  24. 106
  25. 111
  26. 118
  27. 124
  28. 125
  29. 126
  30. 128
  31. 135
  32. 138
  33. 146
  34. 155
  35. 156
  36. 157
  37. 160
  38. 170
  39. 173
  40. 176
  41. 178
  42. 180
  43. 185
  44. 191
  45. 203
  46. 204
  47. 208
  48. 212
  49. 215
  50. 231
  51. 238
  52. 240
  53. 246
  54. 247
  55. 250
  56. 253
  57. 255
  58. 2
  59. 7
  60. 9
  61. 12
  62. 15
  63. 19
  64. 30
  65. 38
  66. 53
  67. 55
  68. 59
  69. 61
  70. 68
  71. 70
  72. 71
  73. 75
  74. 81
  75. 86
  76. 87
  77. 88
  78. 89
  79. 98
  80. 99
  81. 103
  82. 106
  83. 111
  84. 115
  85. 116
  86. 118
  87. 122
  88. 125
  89. 126
  90. 130
  91. 135
  92. 138
  93. 142
  94. 143
  95. 146
  96. 147
  97. 150
  98. 151
  99. 152
  100. 156
  101. 159
  102. 163
  103. 170
  104. 173
  105. 175
  106. 177
  107. 178
  108. 180
  109. 182
  110. 185
  111. 203
  112. 204
  113. 207
  114. 217
  115. 233
  116. 240
  117. 245
  118. 246
  119. 247
  120. 250
  121. 253
  122. 254
  123. 255
  124. 7
  125. 18
  126. 19
  127. 30
  128. 38
  129. 53
  130. 61
  131. 64
  132. 66
  133. 70
  134. 71
  135. 75
  136. 88
  137. 89
  138. 95
  139. 98
  140. 99
  141. 103
  142. 104
  143. 106
  144. 109
  145. 111
  146. 114
  147. 116
  148. 118
  149. 122
  150. 125
  151. 126
  152. 130
  153. 134
  154. 138
  155. 140
  156. 143
  157. 151
  158. 155
  159. 156
  160. 157
  161. 159
  162. 163
  163. 166
  164. 176
  165. 177
  166. 180
  167. 182
  168. 183
  169. 185
  170. 189
  171. 203
  172. 204
  173. 207
  174. 212
  175. 217
  176. 227
  177. 233
  178. 234
  179. 238
  180. 240
  181. 241
  182. 242
  183. 247
  184. 250
  185. 255
  186. 5
  187. 8
  188. 9
  189. 11
  190. 12
  191. 15
  192. 17
  193. 30
  194. 36
  195. 41
  196. 42
  197. 45
  198. 48
  199. 49
  200. 53
  201. 57
  202. 59
  203. 63
  204. 64
  205. 66
  206. 67
  207. 68
  208. 70
  209. 73
  210. 76
  211. 77
  212. 79
  213. 82
  214. 86
  215. 88
  216. 89
  217. 90
  218. 95
  219. 98
  220. 99
  221. 101
  222. 102
  223. 103
  224. 105
  225. 109
  226. 110
  227. 111
  228. 113
  229. 115
  230. 116
  231. 118
  232. 124
  233. 125
  234. 126
  235. 127
  236. 129
  237. 130
  238. 134
  239. 138
  240. 140
  241. 143
  242. 144
  243. 147
  244. 151
  245. 155
  246. 157
  247. 161
  248. 162
  249. 163
  250. 167
  251. 7
  252. 9
  253. 10
  254. 11
  255. 5
  256. 9
  257. 18
  258. 19
  259. 20
  260. 22
  261. 31
  262. 59
  263. 61
  264. 70
  265. 76
  266. 77
  267. 81
  268. 86
  269. 88
  270. 89
  271. 90
  272. 99
  273. 105
  274. 106
  275. 109
  276. 111
  277. 2
  278. 4
  279. 5
  280. 7
  281. 10
  282. 15
  283. 18
  284. 19
  285. 22
  286. 29
  287. 31
  288. 33
  289. 36
  290. 38
  291. 41
  292. 46
  293. 49
  294. 57
  295. 59
  296. 61
  297. 66
  298. 70
  299. 72
  300. 73
  301. 75
  302. 76
  303. 4
  304. 5
  305. 11
  306. 15
  307. 19
  308. 20
  309. 30
  310. 33
  311. 36
  312. 42
  313. 45
  314. 46
  315. 47
  316. 4
  317. 5
  318. 11
  319. 19
  320. 22
  321. 23
  322. 29
  323. 31
  324. 46
  325. 47
  326. 50
  327. 57
  328. 61
  329. 68
  330. 70
  331. 71
  332. 73
  333. 75
  334. 76
  335. 86
  336. 88
  337. 89
  338. 90
  339. 99
  340. 101
  341. 102
  342. 103
  343. 104
  344. 105
  345. 106
  346. 109
  347. 110
  348. 111
  349. 114
  350. 115
  351. 124
  352. 125
  353. 126
  354. 130
  355. 131
  356. 133
  357. 134
  358. 137
  359. 138
  360. 140
  361. 142
  362. 144
  363. 147
  364. 157
  365. 159
  366. 160
  367. 165
  368. 166
  369. 167
  370. 169
  371. 173
  372. 177
  373. 180
  374. 183
  375. 185
  376. 186
  377. 187
  378. 192
  379. 203
  380. 207
  381. 208
  382. 209
  383. 212
  384. 213
  385. 214
  386. 221
  387. 229
  388. 233
  389. 237
  390. 238
  391. 240
  392. 246
  393. 255
  394. 3
  395. 5
  396. 11
  397. 17
  398. 18
  399. 19
  400. 22
  401. 23
  402. 29
  403. 33
  404. 34
复制代码

里面的全是数字,最小值为 1,最大值为 255,我现在要做一个批处理,使我能够分析这个 SearchNet.TXT 中从 1 到 255 的每一个数字出现的次数,出现次数为 0 的,当然不要统计啦。要求得到的统计文档格式如下:

Counter.txt
  1. 2 2
  2. 3 1
  3. 4 3
  4. 5 7
  5. 7 5
  6. 8 1
  7. 9 4
  8. 10 2
  9. 11 5
  10. ...
复制代码
为此,我自己也写了个批处理,但是个人感觉执行效率不够高,才 400 多个数据,分析一下居然消耗了整整 100 秒时间(我的机器为 PIII 800MHz + 256MB PC133 SDRAM),请高手帮我优化一下,谢谢!

Counter.CMD
  1. @echo off
  2. SETLOCAL ENABLEDELAYEDEXPANSION
  3. set tmpfile=search.tmp
  4. set resultfile=counter.txt
  5. if exist %tmpfile% del %tmpfile% /q
  6. if exist %resultfile% del %resultfile% /q
  7. for /f %%i in ('type SearchNET.TXT') do echo a%%ia>>%tmpfile%
  8. for /l %%i in (1,1,255) do (
  9. for /f "tokens=2* delims=::" %%I in ('find /c ^"a%%ia^" %tmpfile%^|find /v ^": 0^"') do (
  10. set /p="%%i%%I">>%resultfile%<nul
  11. echo.>>%resultfile%
  12. )
  13. )
  14. REM del %tmpfile%
  15. ENDLOCAL
复制代码

作者: namejm    时间: 2006-11-23 23:45
  统计的结果中,第一列数字要按照从小到大的顺序显示吗?
作者: namejm    时间: 2006-11-24 00:10
  若第一列数字无须按照从小到大的顺序排列,则可以使用如下代码:

  1. @echo off
  2. set num=-1
  3. sort<SearchNet.TXT>tmp.txt
  4. cd.>result.txt
  5. setlocal enabledelayedexpansion
  6. for /f %%i in (tmp.txt) do (
  7.     set /a num+=1
  8.     set second=!first!
  9.     set first=%%i
  10.     if not "!second!"=="" if !second! neq !first! (>>result.txt echo !second!  !num!&set num=0)
  11. )
  12. >>result.txt echo %first%  %num%
  13. del tmp.txt
  14. start result.txt
复制代码

作者: namejm    时间: 2006-11-24 02:31
  若要对第一列数作升序处理,则可对顶楼的代码修改如下(经过测试,与顶楼的代码相比,以下代码效率有较大提高,但效率最高的是3F的代码):

  1. @echo off
  2. cd.>result.txt
  3. setlocal enabledelayedexpansion
  4. for /l %%i in (1,1,255) do (
  5.     for /f %%j in ('findstr "^%%i$" SearchNet.txt') do  set /a num+=1
  6.     if not !num! equ 0 >>result.txt echo %%i !num!
  7.     set num=0
  8. )
  9. start result.txt
复制代码

[ 本帖最后由 namejm 于 2006-11-24 02:35 AM 编辑 ]
作者: 老毛桃    时间: 2006-11-24 09:43
呵呵,感谢感谢,测试了一下,我办公室电脑为 CD2.8GHz+512MB DDRII,我的代码耗时 24 秒,3F 的代码耗时不到 1  秒,4F 的耗时 14  秒。都比我的快得多。

因为原先不知道 findstr 中还有“$”这么个好咚咚,导致了先在原先的 SearchNet.txt 的每一行家上前后缀,耗去了部分时间,在 Count 的时候又不得不去掉它,效率大大降低了。

但如果我现在想按照里面每个数字出现的频率从高到低排序,又该怎样呢?嘿嘿,又给 Namejm 带来难题了。。。。
作者: namejm    时间: 2006-11-24 20:47
  如果要按照每个数字出现的频率从高到低排序,则可在3F的基础上得到如下代码。这个代码会产生大量的临时文件,并且效率比较低下。请测试:

  1. @echo off
  2. set num=-1
  3. sort<SearchNet.TXT>tmp1.txt
  4. cd.>tmp2.txt
  5. cd.>tmp3.txt
  6. cd.>result.txt
  7. setlocal enabledelayedexpansion
  8. for /f %%i in (tmp1.txt) do (
  9.     set /a num+=1
  10.     set second=!first!
  11.     set first=%%i
  12.     if not "!second!"=="" if !second! neq !first! (>>tmp2.txt echo !second!  !num!&set num=0)
  13. )
  14. >>tmp2.txt echo %first%  %num%
  15. md tmp && pushd tmp
  16. for /f "tokens=2" %%i in (..\tmp2.txt) do fsutil file createnew %%i %%i>nul
  17. >..\tmp3.txt dir /o-s /b
  18. for /f %%i in (..\tmp3.txt) do (
  19.     >>..\result.txt findstr " %%i$" ..\tmp2.txt
  20. )
  21. popd && rd /q /s tmp
  22. del tmp1.txt tmp2.txt tmp3.txt
  23. start result.txt
复制代码

作者: 老毛桃    时间: 2006-11-25 08:38
原帖由 namejm 于 2006-11-24 20:47 发表
  如果要按照每个数字出现的频率从高到低排序,则可在3F的基础上得到如下代码。这个代码会产生大量的临时文件,并且效率比较低下。请测试:

@echo off
set num=-1
sort<SearchNet.TXT>tmp1.txt
cd. ...

嘿嘿,高!不佩服不行了,好好学习一下。。。
作者: namejm    时间: 2006-11-25 12:34
  对6F的代码做了一处改动,效率大为提高,请做对比测试:

  1. @echo off
  2. set num=-1
  3. sort<SearchNet.TXT>tmp1.txt
  4. cd.>tmp2.txt
  5. cd.>tmp3.txt
  6. cd.>result.txt
  7. setlocal enabledelayedexpansion
  8. for /f %%i in (tmp1.txt) do (
  9.     set /a num+=1
  10.     set second=!first!
  11.     set first=%%i
  12.     if not "!second!"=="" if !second! neq !first! (>>tmp2.txt echo !second!  !num!&set num=0)
  13. )
  14. >>tmp2.txt echo %first%  %num%
  15. md tmp && pushd tmp
  16. for /f "tokens=2" %%i in (..\tmp2.txt) do (
  17.     cd.>%%i
  18.     for /l %%j in (1,1,%%i) do echo.>>%%i
  19. )
  20. >..\tmp3.txt dir /o-s /b
  21. for /f %%i in (..\tmp3.txt) do (
  22.     >>..\result.txt findstr " %%i$" ..\tmp2.txt
  23. )
  24. popd && rd /q /s tmp
  25. del tmp1.txt tmp2.txt tmp3.txt
  26. start result.txt
复制代码

作者: 老毛桃    时间: 2006-11-25 13:23
原帖由 namejm 于 2006-11-25 12:34 发表
  对6F的代码做了一处改动,效率大为提高,请做对比测试:

@echo off
set num=-1
sort<SearchNet.TXT>tmp1.txt
cd.>tmp2.txt
cd.>tmp3.txt
cd.>result.txt
setlocal enabledelayedexpa ...

呵呵,厉害厉害啊!
  1. for /f "tokens=2" %%i in (..\tmp2.txt) do fsutil file createnew %%i %%i>nul
复制代码

换成了
  1. for /f "tokens=2" %%i in (..\tmp2.txt) do (
  2.     cd.>%%i
  3.     for /l %%j in (1,1,%%i) do echo.>>%%i
  4. )
复制代码

处理时间由 5 秒变成了 2 秒,佩服啊!

真想给此帖加精,可惜楼主是个只有三脚猫功夫的毛桃!
作者: ccwan    时间: 2006-11-25 14:23
namejm真乃精英啊!强烈要求加精!
作者: namejm    时间: 2006-11-25 17:11
原帖由 老毛桃 于 2006-11-25 01:23 PM 发表

真想给此帖加精,可惜楼主是个只有三脚猫功夫的毛桃!

  名利乃身外之物,加精的目的是能让更多的人来关注,若能让更多的人对DOS批处理感兴趣的话,也不枉我写这几段代码了,这个精华加在谁的名下也就显得不那么重要了。若够得上精华帖的标准,毛桃兄只管加成精华就是了;若够不上精华帖的标准,作为普通帖处理也可。
作者: 老毛桃    时间: 2006-11-25 19:04
原帖由 namejm 于 2006-11-25 17:11 发表

  名利乃身外之物,加精的目的是能让更多的人来关注,若能让更多的人对DOS批处理感兴趣的话,也不枉我写这几段代码了,这个精华加在谁的名下也就显得不那么重要了。若够得上精华帖的标准,毛桃兄只管加成精华 ...

呵呵,的确是将批处理发挥到了极致,至少我是这么认为的,加精,算到 Namejm 兄的名下,哈哈!

收藏备忘,以后常来温习温习。
作者: namejm    时间: 2006-11-25 22:14
原帖由 老毛桃 于 2006-11-25 07:04 PM 发表

呵呵,的确是将批处理发挥到了极致,至少我是这么认为的,加精,算到 Namejm 兄的名下,哈哈!

收藏备忘,以后常来温习温习。

  呵呵,6F代码不是我的原创,关键部分剽窃了DOS联盟里 3742668 的代码,不敢擅专。
作者: namejm    时间: 2006-11-29 13:50
  关于统计字符出现次数,更精彩的批处理代码请参考这个帖子,真正的叫人大开眼界:http://www.cn-dos.net/forum/view ... id=Z6IHFV#pid155049
作者: 老毛桃    时间: 2006-11-29 15:54
原帖由 namejm 于 2006-11-29 13:50 发表
  关于统计字符出现次数,更精彩的批处理代码请参考这个帖子,真正的叫人大开眼界:http://www.cn-dos.net/forum/view ... id=Z6IHFV#pid155049

呵呵,的确精彩,感谢 Namejm
作者: frice    时间: 2006-11-30 14:43
哦哟,这样也可以
真是高
作者: lijiehao    时间: 2006-12-15 23:23
高人啊!一个批处理居然发挥了这么大的作用
作者: bagpipe    时间: 2006-12-16 17:44
只做了统计出现的次数,没有排序....(试发帖)

  1. @echo off&setlocal
  2. set /a n=1
  3. for /f %%a in ('type 1.txt^|sort') do (
  4. call :pp %%a
  5. )
  6. :pp
  7. if not defined bb goto b
  8. if "%bb%"=="%1" (set /a n+=1) else (>>ko.txt echo %bb%  %n%次&set /a n=1)
  9. :b
  10. set bb=%1
  11. goto :eof
复制代码

作者: bagpipe    时间: 2006-12-16 20:47
粗略的写了一下排序

代码如下:


  1. @echo off&setlocal enabledelayedexpansion
  2. set a=[0-9]
  3. for /l %%a in (1,1,3) do (
  4. call :pp !a!
  5. set a=!a![0-9]
  6. )
  7. goto c
  8. :pp
  9. for /f %%x in ('findstr "^%1$" aa.txt^|sort') do @echo %%x >>dd.txt
  10. goto :eof

  11. :c
  12. set /a n=1
  13. for /f %%a in ('type dd.txt') do (
  14. call :pp %%a
  15. )
  16. :pp
  17. if not defined bb goto b
  18. if "%bb%"=="%1" (set /a n+=1) else (>>ko.txt echo %bb%  %n%次&set /a n=1)
  19. :b
  20. set bb=%1
  21. goto :eof
复制代码

作者: namejm    时间: 2006-12-26 20:48
  bagpipe 兄18楼的代码同时保留上一行内容和本行内容的思路十分巧妙;for 语句后括号之后不马上跟跳出语句是个十分容易犯错的地方;不声明启用变量延迟功能可以兼容感叹号,扩大了字符的兼容范围;这段代码言简意赅,堪称经典。相信经过细节方面的改造之后,将会成为统计行内容重复次数的通用代码。

  bagpipe 兄19楼的代码用 for /l 来控制每次 findstr 的字符长度,然后把同一长度的用 sort 来排序,从而突破了 sort 只能按字符位大小来排序这一限制,又是一个超级技巧,可以成为数字排序的一个经典思路。

  对你的敬仰开始泛滥……
作者: ccwan    时间: 2006-12-27 10:30
一定要加精啊!便于大家学习。
作者: thinker1234    时间: 2006-12-28 11:44

我不会
作者: GDH    时间: 2007-11-28 23:55
昏迷啊   最近您对批处理做了基础的研究

没想到看到顶级水平的代码还是晕了头了。。。
作者: haiou327    时间: 2007-11-29 00:42
真乃高手云集啊!!!!!!!!!
作者: 都市浪子666    时间: 2008-1-15 23:35
偶是超级菜鸟。先收藏。日后慢慢研究了。
也不知道要过多少年才能研究得透。。。。55555555
作者: qjj1221    时间: 2008-4-12 15:20
高手中的高手 佩服啊
作者: monkeyhero    时间: 2008-8-5 11:20
哇塞,全是高手啊,学习了
作者: yuzhe    时间: 2008-8-20 19:30
发现自己太渺小了...高人多.
作者: free123456    时间: 2008-10-23 17:43
注意:
3楼的代码有错误,在统计最后一个数字的个数时差一个,最后num+=1即可

[ 本帖最后由 free123456 于 2008-10-23 17:59 编辑 ]




欢迎光临 无忧启动论坛 (http://wuyou.net./) Powered by Discuz! X3.3