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

【练习-036】批处理将数值按要求排序

出题目的:
  1、通过练习掌握数值排序的几种方法
  2、通过练习掌握切分字符串的方法
加分原则:
  满分15分,视情形加分(以思路为重)
解题限制:
  版主级的暂请观看,但可做解题提示
题目如下:
  有a.txt(见一)内容为N列N行不等的4位内数值,通过批处理将所有数值从小到大进行排序,并按6个数值一行输出到b.txt(见二)。

  1. 4981 5487 2724 2419 4837 2218 37 19 2880 5521
  2. 9613 7292 7433 554 8287 1147 9516 5678 9760 3028
  3. 9220 5936 3580 6455 8116 9776 6246 1652 6390 6615
  4. 7855 7707 1850 4564 2454 4571 7330 8718 4499 5083
  5. 7683 3076 637 3644 9714 6080 9554 8250 5353 6692
  6. 4036 9590 4539 8156 7648 6738 8834 7033 4043 9729
  7. 7512 1299 1611 1054 9291 9948 7213 5882 6891 6149
  8. 1159 7604 1290 7426 8342 4907 7802 2285 6828 4547
  9. 940 4594 5470 3831 7949 3308 8553 5841 4532 6151
  10. 2048 4362 7137 6227 1843 2833 119 6124 6716 4435
  11. 6342 132 4637 4359 7482 632 8 35 9999 1023
复制代码


  1. 8 19 35 37 119 132
  2. 554 632 637 940 1023 1054
  3. 1147 1159 1290 1299 1611 1652
  4. 1843 1850 2048 2218 2285 2419
  5. 2454 2724 2833 2880 3028 3076
  6. 3308 3580 3644 3831 4036 4043
  7. 4359 4362 4435 4499 4532 4539
  8. 4547 4564 4571 4594 4637 4837
  9. 4907 4981 5083 5353 5470 5487
  10. 5521 5678 5841 5882 5936 6080
  11. 6124 6149 6151 6227 6246 6342
  12. 6390 6455 6615 6692 6716 6738
  13. 6828 6891 7033 7137 7213 7292
  14. 7330 7426 7433 7482 7512 7604
  15. 7648 7683 7707 7802 7855 7949
  16. 8116 8156 8250 8287 8342 8553
  17. 8718 8834 9220 9291 9516 9554
  18. 9590 9613 9714 9729 9760 9776
  19. 9948 9999
复制代码

[ 本帖最后由 batman 于 2009-2-25 20:31 编辑 ]
***共同提高***

来个效率低下的:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1 1 10000) do (
  3.     for /f "delims=" %%b in (a.txt) do (
  4.         for %%c in (%%b) do (
  5.             if %%a equ %%c set /p= %%a<nul&set /a n+=1&if !n! equ 6 echo\&set n=0
  6. )))
  7. pause
复制代码
(*^_^*)

TOP

原帖由 netbenton 于 2009-5-2 07:31 发表
要是用debug的话,就就应用汇编批令完成了,搞那么多次debug调用,效率太低了一点

那个我不懂嘿嘿

TOP

要是用debug的话,就就应用汇编批令完成了,搞那么多次debug调用,效率太低了一点

TOP

使用debug
  1. @echo off
  2. Setlocal EnableDelayedExpansion
  3. Set fs=1.txt
  4. Set dt=2.txt
  5. Set tf=db-tmp.txt
  6. Set lenb=1
  7. Set "o=>>%tf%"
  8. call :sizehex %fs%
  9. call :consoledb %fs%
  10. ::scan file1
  11. %o% echo s 100 %size% 20
  12. %o% echo q
  13. start /w debug ^<%tf% ^>db-out.txt
  14. ::edit file1
  15. call :consoledb %fs%
  16. for /f "eol=- tokens=2 delims=:" %%a in (db-out.txt) do (
  17. if defined old (
  18. set /a len=0x%%a-old-1
  19. set /a old=0x%%a
  20. if !len! GTR !lenb! Set /a lenb=len
  21. ) else (
  22. set /a old=0x%%a
  23. )
  24. %o% echo e %%a
  25. %o% echo 0A
  26. )
  27. %o% echo w
  28. %o% echo q
  29. start /w debug ^<%tf%
  30. ::output
  31. call :fined >%dt%
  32. call :sizehex %dt%
  33. call :consoledb %dt%
  34. ::scan file2
  35. %o% echo s 100 %size% 0D
  36. %o% echo q
  37. start /w debug ^<%tf% ^>db-out.txt
  38. ::edit file2
  39. call :consoledb %dt%
  40. for /f "eol=- tokens=2 delims=:" %%a in (db-out.txt) do (
  41. set /a count+=1,line=count%%6
  42. if !line! NEQ 0 (
  43. %o% echo e %%a
  44. %o% echo 20 20
  45. )
  46. )
  47. %o% echo w
  48. %o% echo q
  49. start /w debug ^<%tf%
  50. pause
  51. del db-???.txt
  52. goto :eof
  53. :fined
  54. set reg=%reg%[0-9]
  55. if %lenb% EQU 0 goto :eof
  56. set /a lenb-=1
  57. more %fs%|findstr /b /e %reg%|sort
  58. call :fined
  59. goto :eof
  60. :consoledb
  61. >%tf% cd.
  62. %o% echo n%1
  63. %o% echo l
  64. goto :eof
  65. :sizehex
  66. set /a size=%~z1/16*10
  67. goto :eof
复制代码

TOP

我也练练手

@echo off&setlocal enabledelayedexpansion
(set m=
for /f "delims=" %%a in (a.txt) do (
    for %%b in (%%a) do (
        set "one=0000%%j"&set/a m+=1&set _!num:~-4!_!m!=%%j
)  )
set n=6&set str=
for /f "tokens=2 delims==" %%i in ('set _') do (
    set str=!str! !%%i
    set/a n-=1,1/n||(set n=6&echo !str!&set str=)
)
if defined str echo !str!)>b.txt
start "b.txt"

TOP

回楼上随风兄,我试了这样修改下能处理重复,不知通用么。
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%i in ('more a.txt') do (
  3. for %%j in (%%i) do (
  4. set "num=0000%%j"&set "num=!num:~-4!"
  5. if defined _!num! (set/a m+=1&set _!num!!m!=%%j
  6. ) else set _!num!=%%j
  7. ))
  8. for /f "tokens=2 delims==" %%i in ('set _') do (
  9. <nul set/p=%%i >>b.txt
  10. set/a n+=1
  11. if !n! equ 6 echo.>>b.txt&set/a n=0
  12. )
  13. start "" "b.txt"
复制代码

[ 本帖最后由 zhouyongjun 于 2009-3-3 12:11 编辑 ]

TOP

回复 31楼 的帖子

for /f + findstr 效率很低。
应该与先将findstr的结果保存到文件,再for /f 解析文件差不多。
理论上好像是这样的,但事实不是。
findstr 无论是遍历、还是写入文件,速度都是超快的,但如果把findstr运行的结果
直接赋值给for就没有充分利用findstr命令的优势了。
事实上 for 的in 中嵌套任何命令都是影响效率的,
比如我们常用的
for /f "delims=" %%a in ('dir/b') do ......
for /f "delims=" %%a in ('set .') do ......
等等,只是在少量的数据、或少量的使用次数面前体现不出来。
废话少说,测试以下代码,应该会有所发现。
a.txt 内容至少 5万行
代码一、
  1. for /f "delims=" %%a in ('findstr .* a.txt') do echo %%a
复制代码
代码二、
  1. findstr .* a.txt>b.txt
  2. for /f "delims=" %%a in (b.txt) do echo %%a
复制代码
回复 32 楼 楼主
设置变量的方法确实好,不过有一个缺点是无法处理重复的数字
在实际应用中,对大量的数字排序,不重复的数字应该不多吧。。^_^
技术问题请到论坛发帖求助!

TOP

&&没想到这个贴子引发了众位管理员对处理数据的一番激烈议论,各位也给出了精彩的代
码,看得我目不暇接眼花缭乱,确实是学习了。
  对于数据的处理,本人还是偏爱于设置变量法,jm说这种方法会消耗系统内存,确实是
如此,经本人亲自实验,按现在的一般机器配置,设置1000000个变量(仅实验到百万)对
系统的运行不会造成明显的影响。因此,设置变量法还是合适处理海量的数据的。
  下面给出本人的解:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (a.txt) do (
  3.     for %%b in (%%a) do set "a=####%%b"&set "_!a:~-4!=a"
  4. )
  5. for /f "tokens=1 delims=#_=" %%a in ('set _') do (
  6.      set /a n+=1,m=n%%6
  7.      set /p=%%a        <nul>>b.txt
  8.      if !m! equ 0 echo.>>b.txt
  9. )
  10. start b.txt
复制代码
  
***共同提高***

TOP

回复 28楼 的帖子

因为 for /f + findstr 效率很低。

你说的是把findstr嵌在in里面吗?理论上效率应该不会很低吧。
应该与先将findstr的结果保存到文件,再for /f 解析文件差不多。findstr的效率不低。要实现六列一行,用for /f是必不可少的。

====================================
是在 for /f 的 in 中命令的运行方式(cmd /c command)影响效率吗?
因为要额外启动一个CMD,所以速度要慢一点。但应该不影响解析效率吧。
照这样说,所有用 for /f 解析命令输出的方法都对速度有一定影响,也就是增加了总的运行时间,折算起来就相当于降低了效率。


PS:19楼代码中 findstr /rxg:~a.txt t.txt,t.txt前面写掉了~。

[ 本帖最后由 zqz0012005 于 2009-2-27 08:49 编辑 ]
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

为21楼加点注释以便初学者阅读

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. ::把原始数据转换成每行只有一个数字的形式
  4. (for /f "usebackq tokens=*" %%i in ("a.txt") do (
  5.   for %%j in (%%i) do (
  6.     ::在每个数字的最左侧补上三个空格
  7.     set "str=   %%j"
  8.     ::截取补空格以后的字符串的最右侧四位
  9.     ::最终的结果就是把所有数字全部补成四个字符(不足四位的在左侧补空格)
  10.     ::这样的做的原因是sort排序时是按照字符ASCII逐位比较的
  11.     echo !str:~-4!
  12.   )
  13. ))>"%temp%\GridNum.txt"
  14. ::利用tokens=*忽略行首空格的特性来删除前面补的空格
  15. for /f "tokens=*" %%i in ('sort "%temp%\GridNum.txt"') do (
  16.   set /a n+=1
  17.   ::对6取余是实现六列一行的关键
  18.   set /a n%%=6
  19.   if !n! equ 0 (
  20.     echo !var:~1! %%i
  21.     set "var="
  22.   ) else (
  23.     set var=!var! %%i
  24.   )
  25. )
  26. if not "!var!"=="" (
  27.   echo !var:~1!
  28. )
复制代码
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

为23楼加点注释以便初学者阅读

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. ::把原始数据转换成每行只有一个数字的形式
  4. (for /f "usebackq tokens=*" %%i in ("a.txt") do (
  5.   for %%j in (%%i) do (
  6.     echo %%j
  7.   )
  8. ))>tem
  9. ::分别对一位、二位、三位、四位数字进行sort排序
  10. ::这样的做的原因是sort排序时是按照字符ASCII逐位比较的
  11. for /l %%i in (1 1 4) do (
  12.   if "!t!"=="" (
  13.     ::定义这样的变量是为了在后面的findstr正则表达式中匹配任意一位0到9之间的数字
  14.     set t=[0-9]
  15.   ) else (
  16.     ::在后面的findstr正则表达式中分别匹配二位、三位、四位数字
  17.     set t=[0-9]!t!
  18.   )
  19.   ::控制参与sort排序的数字位数
  20.   ::在findstr正则表达式中<string>表示精确匹配
  21.   ::结合外层for循环实现分别对一位、二位、三位、四位数字进行sort排序
  22.   for /f %%i in ('findstr "\<!t!\>" tem^|sort') do (
  23.     set /a n+=1
  24.     ::对6取余是实现六列一行的关键
  25.     set /a n%%=6
  26.     if !n! equ 0 (
  27.       echo !var:~1! %%i
  28.       set "var="
  29.     ) else (
  30.       set var=!var! %%i
  31.     )
  32.   )
  33. )
  34. if not "!var!"=="" (
  35.   echo !var:~1!
  36. )
复制代码
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

忍不住,也发两个凑凑热闹。
代码一、
不生成临时文件,适合处理少量数据。可以处理重复数字。
  1. @echo off
  2. if "%~1"=="" (
  3.   setlocal enabledelayedexpansion&set /a n=0
  4.   for /f "tokens=* delims=0" %%a in ('%~s0 h^|sort') do (
  5.      set /a n+=1,n=n%%6
  6.      set /p=%%a <nul
  7. if !n! equ 0 echo.
  8.    )
  9.   pause&exit
  10. )
  11. setlocal enabledelayedexpansion
  12. for /f "usebackq tokens=*" %%i in ("a.txt") do (
  13.    for %%j in (%%i) do set m=0000000000%%j&echo !m:~-10!
  14. )
  15. endlocal
  16. goto :EOF
复制代码
代码二、
需确定最高位是多少。
生成一个临时文件也可以,不过既然已经生成了临时文件,不防再多生成一个以提高效率。
因为 for /f + findstr 效率很低。
适合处理海量数据。
  1. @echo off&setlocal enabledelayedexpansion
  2. (for /f "usebackq tokens=*" %%i in ("a.txt") do (
  3.     for %%j in (%%i) do echo %%j
  4. ))>tem
  5. sort tem>tem2
  6. cd.>tem
  7. for /l %%a in (1 1 4) do (
  8.    set num=.!num!
  9.    findstr /x !num! tem2>>tem
  10. )
  11. for /f "delims=" %%a in (tem) do (
  12.      set /a n+=1,n=n%%6
  13.      set /p=%%a <nul
  14. if !n! equ 0 echo.
  15. )
  16. echo.&pause
复制代码
1

评分人数

    • namejm: 好代码,一出就是两个。PB + 10
技术问题请到论坛发帖求助!

TOP

原帖由 随风 于 2009-2-26 20:31 发表
'type tem^|sort' 为何不写成  sort tem

这就改  谢

TOP

回复 21楼 的帖子

'type tem^|sort' 为何不写成  sort tem
技术问题请到论坛发帖求助!

TOP

返回列表