Board logo

标题: 【出题】批处理给文本文件ab cd.txt每行前加上日期 [打印本页]

作者: 随风    时间: 2008-10-18 22:22     标题: 【出题】批处理给文本文件ab cd.txt每行前加上日期

出题:给ab cd.txt每行前加上日期
已知:
   ab cd.txt 文件名含空格。(不能改文件名)
   ab cd.txt 行数不确定 (大约5万行左右),无空行,且不含特殊符号。
.
要求:
   1、给ab cd.txt每行前面加上日期,将结果写入 c.txt
   2、最后一行为当前日期,倒数第二行为昨天的日期,倒数第三行为前天的日期,依此类
推。。。。
   3、并在跨月份时插入空行。
   如:09月30日 和 10月01日 之间需插入一空行。
  1.    2008年09月28日 为什么要学习批处理
  2.    2008年09月29日 1.源自于批处理的简单
  3.    2008年09月30日 我想没有多少人愿意花上一个月甚至更多的时间
  4.    2008年10月01日 去绞尽脑汁的专门学习一个编程语言来写一个删除系统垃圾的程序,
  5.    2008年10月02日 因为对于一个不是专门学习计算机或者将来从事这方面工作的人来说,
  6.    2008年10月03日 这样的投入与产出实在是不值得的,
  7.    2008年10月04日 而用我们的批处理只要几分钟就可以解决这个问题,
复制代码
代码要求:
  1、不产生临时文件
  2、用纯p解决。
  3、必须考虑跨年度、跨月份、及闰年的情况。
  4、代码运行耗时不能超过一分钟。
.
加分条件:
   1、效率高   +5
   2、代码简洁 +3
   3、满分    +10
.

假设ab cd.txt内容为:
  1. 为什么要学习批处理
  2. 1.源自于批处理的简单
  3. 我想没有多少人愿意花上一个月甚至更多的时间
  4. 去绞尽脑汁的专门学习一个编程语言来写一个删除系统垃圾的程序,
  5. 因为对于一个不是专门学习计算机或者将来从事这方面工作的人来说,
  6. 这样的投入与产出实在是不值得的,
  7. 而用我们的批处理只要几分钟就可以解决这个问题,
  8. 这样的方便性让任何对计算机望而生畏的人来说是多么的有吸引力。
  9. 2.通过批处理的编写,会逐渐的熟悉windows操作系统的一些细节问题,
  10. 仅此一点就能让你在众多菜鸟中脱颖而出。
  11. 3.通过diy自己的“程序”让自己有种成就感,
  12. 这种感觉绝对不是使用别人的工具所能言语的,
  13. 自己能写出来东西就是对自己最好的证明。
  14. 4.强大性,baidu,google里不可能搜索到能帮你解决掉所有问题的程序,
  15. 如果你不会写那些.exe程序,
  16. 那么你要完成你的目标可能就要花些银子让一些软件工作室帮你写咯。
  17. 其实决大部分系统的问题,.bat都可以轻松的帮你解决掉了。
  18. 说了这么多,到底为什么要学习批处理就是很简单的一句话:
  19. 程序是写出来满足绝大部分人的,而批处理是满足我们自己的。
  20. 每个拥有计算机和懂计算机的人都应该学习批处理。
  21. 因为世界上任何一个人都能通过简单的学习掌握批处理这门“编程语言”
复制代码
假设当前日期为: 2008年10月18日
要求 c.txt 结果如下:
  1. 2008年09月28日 为什么要学习批处理
  2. 2008年09月29日 1.源自于批处理的简单
  3. 2008年09月30日 我想没有多少人愿意花上一个月甚至更多的时间
  4. 2008年10月01日 去绞尽脑汁的专门学习一个编程语言来写一个删除系统垃圾的程序,
  5. 2008年10月02日 因为对于一个不是专门学习计算机或者将来从事这方面工作的人来说,
  6. 2008年10月03日 这样的投入与产出实在是不值得的,
  7. 2008年10月04日 而用我们的批处理只要几分钟就可以解决这个问题,
  8. 2008年10月05日 这样的方便性让任何对计算机望而生畏的人来说是多么的有吸引力。
  9. 2008年10月06日 2.通过批处理的编写,会逐渐的熟悉windows操作系统的一些细节问题,
  10. 2008年10月07日 仅此一点就能让你在众多菜鸟中脱颖而出。
  11. 2008年10月08日 3.通过diy自己的“程序”让自己有种成就感,
  12. 2008年10月09日 这种感觉绝对不是使用别人的工具所能言语的,
  13. 2008年10月10日 自己能写出来东西就是对自己最好的证明。
  14. 2008年10月11日 4.强大性,baidu,google里不可能搜索到能帮你解决掉所有问题的程序,
  15. 2008年10月12日 如果你不会写那些.exe程序,
  16. 2008年10月13日 那么你要完成你的目标可能就要花些银子让一些软件工作室帮你写咯。
  17. 2008年10月14日 其实决大部分系统的问题,.bat都可以轻松的帮你解决掉了。
  18. 2008年10月15日 说了这么多,到底为什么要学习批处理就是很简单的一句话:
  19. 2008年10月16日 程序是写出来满足绝大部分人的,而批处理是满足我们自己的。
  20. 2008年10月17日 每个拥有计算机和懂计算机的人都应该学习批处理。
  21. 2008年10月18日 因为世界上任何一个人都能通过简单的学习掌握批处理这门“编程语言”
复制代码

[ 本帖最后由 随风 于 2008-10-18 22:33 编辑 ]
作者: terse    时间: 2008-10-18 22:38

可以做到 但效率不理想
作者: 随风    时间: 2008-10-18 22:48

这个应该难不住 terse 兄,效率问题只要写代码时多费费脑筋就ok了   ^_^

5 万行 一分钟左右 。。。。
这个效率应该可以接受。

这是帮一朋友写代码时想到的,若不讲究效率则此题就不难了。
对批处理的语法要求更高,对入门不久的新手应该是很好的练手题目。。。
作者: zqz0012005    时间: 2008-10-18 22:49

这题主要麻烦在日期处理,其他没什么。关于日期处理cn-dos有很多现成的代码。我也不想再去找了。

以前在cn-dos收集的代码,修理硬盘备份在同学的电脑上,后来被他删了。扁死他也找不回来了。也没有时间和那份心情再去重新收集
作者: rat    时间: 2008-10-18 22:53

纯P是不是不让调外部命令?
可以用reg.exe么?
作者: 随风    时间: 2008-10-18 23:01

用 reg ?
没有任何思路。。
只要是系统自带的命令都可以。
期待结果。。。
作者: terse    时间: 2008-10-19 01:09

1867年计算到2008 整4分
重新整理下再看
作者: zqz0012005    时间: 2008-10-19 03:55

批处理对日期的处理实在麻烦,来个vbs先
  1. Set fso = CreateObject("Scripting.FileSystemObject")
  2. set f = fso.OpenTextFile("ab cd.txt")
  3. f.ReadAll : lines = f.Line : f.Close
  4. set f = fso.OpenTextFile("ab cd.txt")
  5. Do While f.AtEndOfStream <> True
  6.     s =s & GetDate(f.Line) & " " & f.ReadLIne & vbCrLf
  7. Loop
  8. fso.OpenTextFile("c.txt",2,True).Write s
  9. Function GetDate(nDiff)
  10.     nDate = DateAdd("d", nDiff-lines, date)
  11.     if month(nDate) <> month(nDate-1) then strMonChange = vbCrLf
  12. GetDate = strMonChange & _
  13.         year(nDate) & "年" & _
  14.         right("0" & month(ndate), 2) & "月" & _
  15.         right("0" & day(ndate), 2) & "日"
  16. End Function
复制代码

作者: batman    时间: 2008-10-19 08:50

哈哈,小楼兄摆明的是在出难题啊,经测算日期计算只能用32秒左右的时间,确实是个挑战。。。

[ 本帖最后由 batman 于 2008-10-19 09:21 编辑 ]
作者: batman    时间: 2008-10-19 11:40     标题: 抛砖了!!!

仅做到日期从当前开始输出:
测试文本生成代码:
  1. @echo off&for /l %%i in (1,1,50000) do echo %%i>>"ab cd.txt"
复制代码
解题代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. set "t=%time%"&echo.>c.txt
  3. set /a year=%date:~,4%,month=1%date:~5,2%%%100,day=1%date:~8,2%%%100,yun=29
  4. for /f "usebackq delims=" %%i in ("ab cd.txt") do (
  5.     echo !year!-!month!-!day! %%i>>c.txt
  6.     set /a day-=1
  7.     if !day! equ 0 (
  8.        echo.>>c.txt
  9.        set /a month-=1
  10.        if !month! equ 0 (
  11.           set /a year-=1,month=12,day=31&call :lp1
  12.           ) else (
  13.           call :lp2
  14.        )
  15.     )
  16. )
  17. echo 程序开始时间为:%t%
  18. echo 程序结束时间为:%time%
  19. pause>nul&goto :eof
  20. :lp1
  21. set /a a=year%%4,b=year%%100,c=year%%400,yun=28
  22. if %b% equ 0 (
  23.    if %c% equ 0 set "yun=29"
  24.    ) else (
  25.    if %a% equ 0 set "yun=29"
  26. )
  27. goto :eof     
  28. :lp2
  29. for /f "tokens=%month%" %%a in ("1#31 2#%yun% 3#31 4#30 5#31 6#30 7#31 8#31 9#30 10#31 11#30 12#31") do (
  30.     for /f "tokens=2 delims=#" %%i in ("%%a") do set "day=%%i"
  31. )
复制代码
经pusofalse版主提醒修改部分代码后再测试(本人机子慢了),测试时间如下:
作者: batman    时间: 2008-10-19 12:34

日期反过来输出不是做不到,只是一时只想到设置变量的办法,但设置50000个变量就根本谈不上效率了。。。不知随风兄有何妙法?
作者: terse    时间: 2008-10-19 13:46

我是这样处理的  确定文本行数  然后就是总行数之前的日期   开始累加1  直到文本结束
似乎效率不理想
代码简化一下  但效率没上去
本想以年为递减  结果有差错  改回
  1. @echo off
  2. echo 开始时间 %time%
  3. for /f "tokens=1-3 delims=-/\:. " %%i in ("%date%") do set /a p1=%%i,p2=100%%j%%100,p3=100%%k%%100
  4. set/a PN2="!(p1%%4) & !(!(p1%%100)) | !(p1%%400)",PN2+=28
  5. for /f "tokens=%p2%" %%i in ("31 !pN2! 31 30 31 30 31 31 30 31 30 31") do set pt=%%i
  6. for /f "delims=" %%i in ('type "abcd.txt"^|find /v /c ""') do set /a tt=%%i
  7.     cd.>b.txt
  8.     setlocal enabledelayedexpansion
  9.     for /f "usebackq delims=" %%i in ("abcd.txt") do (
  10.     if not defined b set b=p&call :lp
  11.     if !p3! gtr !pt! set/a p3-=pt,p2+=1&call:next
  12.     if !p2! lss 10 (set m2=0!p2!)else set m2=!p2!
  13.     if !p3! lss 10 (set d3=0!p3!)else set d3=!p3!
  14.     >>b.txt echo !p1!年!m2!月!d3!日 %%i
  15.     if !p3! equ !pt! >>b.txt echo.
  16.     set/a p3+=1
  17. )
  18.     echo 结束时间 %time%
  19.     pause&exit /b
  20. :next
  21.     if !p2! gtr 12 set/a PN2="^!(p1%%4) & ^!(^!(p1%%100)) | ^!(p1%%400)",PN2+=28,p1+=1,p2=p2%%12
  22.     for /f "tokens=%p2%" %%i in ("31 !pN2! 31 30 31 30 31 31 30 31 30 31") do set pt=%%i
  23.     goto :eof
  24. :lp
  25.     set/a p2-=1
  26.     if %p2% equ 0 set/a PN2="^!(p1%%4) & ^!(^!(p1%%100)) | ^!(p1%%400)",PN2=28+PN2,p1-=1,p2=12
  27.     for /f "tokens=%p2%" %%i in ("31 %pN2% 31 30 31 30 31 31 30 31 30 31") do set/a p3+=%%i&set pt=%%i
  28.     if %p3% leq %tt% goto lp
  29.     set/a p3-=tt
  30.     goto :eof
复制代码


再修正一下  以年递减 不满一年 以月递减
修正一个 在行数小的情况出现的BUG
  1. @echo off
  2. echo 开始时间 %time%
  3. for /f "tokens=1-3 delims=-/\:. " %%i in ("%date%") do set /a p1=%%i,p2=100%%j%%100,p3=100%%k%%100
  4.     set/a pn="!(p1%%4) & !(!(p1%%100)) | !(p1%%400)",pn+=28,pn2=pn+31
  5.     for /f "tokens=%p2%" %%i in ("31 %pn% 31 30 31 30 31 31 30 31 30 31") do set pt=%%i
  6.     for /f "tokens=%p2%" %%i in ("0 31 %pn2% 90 120 151 181 212 243 273 304 334") do set/a p3+=%%i
  7.     for /f "delims=" %%i in ('type "ab cd.txt"^|find /v /c ""') do set /a tt=%%i-1
  8.     if %tt% gtr %p3% (set/a tt-=p3,p1-=1,p2=12,p3=31)else goto lp2
  9. :lp
  10.     set/a pn="!(p1%%4) & !(!(p1%%100)) | !(p1%%400)",pn+=365
  11.     if %tt% gtr %pn% set/a tt-=pn,p1-=1&goto lp
  12.     set/a pn="!(p1%%4) & !(!(p1%%100)) | !(p1%%400)",pn+=28
  13. :lp1
  14.     if %p3% gtr %tt% goto lp2
  15.     set/a p2-=1
  16.     for /f "tokens=%p2%" %%i in ("31 %pn% 31 30 31 30 31 31 30 31 30 31") do set/a p3+=%%i&set pt=%%i
  17.     if %p3% leq %tt% goto lp1
  18. :lp2
  19.     set/a p3-=tt
  20.     cd.>b.txt
  21.     setlocal enabledelayedexpansion
  22.     for /f "usebackq delims=" %%i in ("ab cd.txt") do (
  23.     if !p3! gtr !pt! set/a p3-=pt,p2+=1&call:next
  24.     if !p2! lss 10 (set m2=0!p2!)else set m2=!p2!
  25.     if !p3! lss 10 (set d3=0!p3!)else set d3=!p3!
  26.     >>b.txt echo !p1!年!m2!月!d3!日 %%i
  27.     if !p3! equ !pt! >>b.txt echo.
  28.     set/a p3+=1
  29. )
  30.     echo 结束时间 %time%
  31.     pause&exit /b
  32. :next
  33.     if !p2! gtr 12 set/a pn="^!(p1%%4) & ^!(^!(p1%%100)) | ^!(p1%%400)",pn+=28,p1+=1,p2=p2%%12
  34.     for /f "tokens=%p2%" %%i in ("31 !pn! 31 30 31 30 31 31 30 31 30 31") do set pt=%%i
  35.     goto :eof
复制代码

[ 本帖最后由 terse 于 2008-10-20 13:48 编辑 ]
作者: batman    时间: 2008-10-19 19:40

看了这段代码,人都要晕了。。。。我也想过用这种方法,但这样效率肯定是上不去的,因
为这样要进行100000次日期计算,其中还要进行很多次的判断,但另一种平常好用的设置
变量法实践中效率更低(变量数量太大了),所以一直未能达到小楼兄的要求。。。
用kip的方法可以将文本未行变成首行,但输出就整个是反过来的,即当前日期和未行成了第
一行,再用一次skip就可以按要求输出了,但这样既显得罗索,效率也达不到一分左右完成
这一要求,同时可能还要生成一次临时文件。。。
期待小楼兄的答案。。。
作者: rat    时间: 2008-10-19 20:27

  1. @echo %time%
  2. @echo off & setlocal enabledelayedexpansion
  3. set sOldFile="ab cd.txt"
  4. set sNewFile="c.txt"
  5. for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do set /a i += 1 && set iM!i!=%%a
  6. for /f "tokens=1-3 delims=-" %%a in ("%date%") do set iThisYear=%%a & set iThisMonth=%%b & set iThisDay=%%c
  7. set /a iLeapYearCount = (iThisYear - 1) / 4 - (iThisYear - 1) / 100 + (iThisYear - 1) / 400
  8. call :GetFebDayCount %iThisYear% iM2
  9. for /l %%a in (1, 1, %iThisMonth%) do if %%a lss %iThisMonth% set /a iThisMonthToDayCount += iM%%a
  10. set /a iAllDayCount = 365 * (iThisYear - 1) + iLeapYearCount + iThisMonthToDayCount + iThisDay
  11. for /f "usebackq delims=" %%a in (%sOldFile%) do set /a iDayDiff += 1
  12. set /a iFirstDayCount = iAllDayCount - (iDayDiff - 1)
  13. set /a iTempYear = iFirstDayCount / 365 - 1
  14. :GetDate
  15. set /a iTempLeapCount = iTempYear / 4 - iTempYear / 100 + iTempYear / 400
  16. set /a iTempDayCount = iFirstDayCount - 365 * iTempYear - iTempLeapCount
  17. if %iTempDayCount% lss 0 set /a iTempYear -= 1 && goto :GetDate
  18. if %iTempDayCount% equ 0 set /a iYear = iTempYear, iMonth = 12, iDay = 31 && goto :WriteText
  19. set /a iYear = iTempYear + 1
  20. call :GetFebDayCount %iYear% iM2
  21. for /l %%a in (1, 1, 12) do (
  22. set /a iTempDayCount -= iM%%a
  23. if !iTempDayCount! leq 0 set /a iMonth = %%a, iDay = iM%%a + iTempDayCount, iTempDay = iM%%a && goto :WriteText
  24. )
  25. :WriteText
  26. cd.>%sNewFile%
  27. for /f "usebackq delims=" %%a in (%sOldFile%) do (
  28. if !iMonth! lss 10 (set sMonth=0!iMonth!) else (set sMonth=!iMonth!)
  29. if !iDay! lss 10 (set sDay=0!iDay!) else (set sDay=!iDay!)
  30. >>%sNewFile% echo !iYear!年!sMonth!月!sDay!日 %%a
  31. if !iDay! lss !iTempDay! (
  32. set /a iDay += 1
  33. ) else (
  34. >>%sNewFile% echo.
  35. if !iMonth! lss 12 (
  36. set /a iMonth += 1, iDay = 1
  37. ) else (
  38. set /a iYear += 1, iMonth = 1, iDay = 1
  39. call :GetFebDayCount !iYear! iM2
  40. )
  41. set /a iTempDay = iM!iMonth!
  42. )
  43. )
  44. echo %time%
  45. pause
  46. exit /b
  47. :GetFebDayCount
  48. for %%a in (4 100 400) do set /a r%%a=%1%%%%a
  49. set %2=28
  50. if %r400%==0 (set %2=29) else (if %r4%==0 if not %r100%==0 set %2=29)
复制代码

[ 本帖最后由 rat 于 2008-10-20 16:55 编辑 ]
作者: terse    时间: 2008-10-19 23:25

原帖由 batman 于 2008-10-19 19:40 发表
看了这段代码,人都要晕了。。。。我也想过用这种方法,但这样效率肯定是上不去的,因
为这样要进行100000次日期计算,其中还要进行很多次的判断,但另一种平常好用的设置
变量法实践中效率更低(变量数量太大了) ...

其实没有进行100000次日期计算  假设50000行 就是50000次运算啊  其中判断少不了的
作者: batman    时间: 2008-10-20 02:34

终于将效率问题解决了,但代码确实难读了。。。
说明一下:先计算出文本的总行数,然后用渐近法计算出第一个日期(先算年再算月和日)
,然后再用for在按行读取数据时进行日期的累加和输出到新文本。
  1. @echo off&setlocal enabledelayedexpansion
  2. set "t=%time%"&echo.>c.txt
  3. rem 提出当前的年月日数值
  4. set /a year=%date:~,4%,month=1%date:~5,2%%%100,day=1%date:~8,2%%%100
  5. rem 设置变量
  6. for %%i in (31 29 31 30 31 30 31 31 30 31 30 31) do (
  7.     set /a num+=1&set "_!num!=%%i"
  8.     set "code1=!code1! %%i"&set "code2=!code2! !num!#%%i"
  9. )
  10. rem 获取文本总行数
  11. for /f "usebackq delims=" %%i in ("ab cd.txt") do set /a n+=1
  12. rem 计算并减去本年已过的天数
  13. set /a n=n-day
  14. for %%a in (%code1%) do (
  15.     if "!m!" neq "%month%" (
  16.        set /a n-=%%a,m+=1
  17.        ) else (
  18.        goto lp1
  19.    )
  20. )
  21. :lp1
  22. rem 计算初始年份
  23. set /a year-=1,n-=365
  24. set /a a=year%%4,b=year%%100,c=year%%400,yun=28,_2=28
  25. if %b% equ 0 (
  26.    if %c% equ 0 set /a n-=1,yun+=1,_2+=1
  27.    ) else (
  28.    if %a% equ 0 set /a n-=1,yun+=1,_2+=1
  29. )
  30. if %n% geq 0 goto lp1
  31. set "code1=!code1:29=%yun%!"&set "code2=!code2:29=%yun%!"
  32. rem 计算初始月份和日期
  33. for %%a in (%code2%) do (
  34.     for /f "tokens=1,2 delims=#" %%i in ("%%a") do (
  35.         set /a n+=%%j
  36.         if !n! geq 0 set /a month=%%i-1,day=%%j-n&goto next
  37.     )
  38. )
  39. :next
  40. rem 核心代码部分,读取文本内容并递加日期,输出到新文本
  41. for /f "usebackq delims=" %%i in ("ab cd.txt") do (
  42.     set /a n=day-_!month!
  43.     if !n! gtr 0 call :lp2
  44.     if !month! geq 10 (
  45.        if !day! geq 10 (
  46.           echo !year!年!month!月!day!日 %%i>>c.txt
  47.           ) else (
  48.           echo !year!年!month!月0!day!日 %%i>>c.txt
  49.        )
  50.        ) else (
  51.        if !day! geq 10 (
  52.           echo !year!年0!month!月!day!日 %%i>>c.txt
  53.           ) else (
  54.           echo !year!年0!month!月0!day!日 %%i>>c.txt
  55.        )
  56.     )
  57.     set /a day+=1
  58. )
  59. echo 开始时间:%t%
  60. echo 结束时间:%time%
  61. pause>nul&goto :eof
  62. :lp2
  63. rem 子程序:跨月、跨年的计算和判断
  64. echo.>>c.txt
  65. set /a month+=1,day=1
  66. if %month% equ 13 (
  67.    set /a year+=1,month=1,a=year%%4,b=year%%100,c=year%%400,_2=28
  68.    if !b! equ 0 (
  69.       if !c! equ 0 set "_2=29"
  70.       ) else (
  71.       if !a! equ 0 set "_2=29"
  72.    )
  73. )
复制代码

[ 本帖最后由 batman 于 2008-10-20 03:40 编辑 ]
作者: 随风    时间: 2008-10-20 15:09

呵呵,对效率的考验。。
各位都出了精彩的代码了。
暂时没时间细看代码,下回去慢慢看。。。
初步做了下测试。


16楼 batman 耗时 0 小时 1 分钟 5 秒 31 毫秒

14楼 rat 耗时 0 小时 0 分钟 57 秒 40 毫秒

12楼 terse 耗时 0 小时 1 分钟 7 秒 75 毫秒

本人目前的代码 耗时: 0 小时 0 分钟 13 秒 72 毫秒
代码在U盘,下次发出来。

其实思路很简单,先获取总行数,并得到N 天前的日期。再逐日递加日期。
作者: terse    时间: 2008-10-20 15:50

原帖由 随风 于 2008-10-20 15:09 发表
呵呵,对效率的考验。。
各位都出了精彩的代码了。
暂时没时间细看代码,下回去慢慢看。。。
初步做了下测试。


16楼 batman 耗时 0 小时 1 分钟 5 秒 31 毫秒

14楼 rat 耗时 0 小时 0 分钟 57 秒 40 毫秒 ...


13秒的处理 真高效
说实话 我想尽办法也没有让代码的效率的提高
我想我的以年递减 在确定日期方面一个也快的了
就是递加和判断方面  我想是少不了一条一条判断的
期待 随风兄的精彩代码
作者: batman    时间: 2008-10-20 16:15

下面是我对自己16楼代码的测试结果:

但13秒多的速度,确实让人期待。。。
作者: pusofalse    时间: 2008-10-20 16:54

  1. @echo off&setlocal enabledelayedexpansion
  2. cd.>c.txt
  3. echo %time%
  4. for %%a in (1 3 5 7 8 10 12) do set _%%a=31
  5. for %%a in (4 6 9 11) do set _%%a=30
  6. for /f "tokens=1-3 delims=- " %%a in ("%date%") do set/a "Year=%%a,Month=100%%b%%100,Day=100%%c%%100+1"
  7. for /f "delims=:" %%a in ('findstr /n /v $ "ab cd.txt"') do set /a "Line=%%a,Feb=28+^!(year%%4)"
  8. set "Monthes=1#31 2#%Feb% 3#31 4#30 5#31 6#30 7#31 8#31 9#30 10#31 11#30 12#31"
  9. for %%i in (%Monthes%) do for /f "tokens=1,2 delims=#" %%a in ("%%i") do if %%a leq %Month% set /a DayCount+=%%b
  10. for /f "tokens=%month%" %%a in ("%Monthes%") do for /f "tokens=1,2 delims=#" %%i in ("%%a") do set/a DayCount-=%%j-Day
  11. set /a LineTemp=Line-DayCount
  12. :loop
  13. set/a "LineTemp-=365+(^!(year%%4)&^!(^!(year%%100))|^!(year%%400)),Year-=1"
  14. if %LineTemp% geq 365 goto loop
  15. set/a "Year-=1,Month=12,Feb=28+^!(Year%%4)"
  16. :loop1
  17. if %LineTemp% gtr !_%Month%! (
  18.    for /f "tokens=%Month%" %%a in ("1#31 2#%Feb% 3#31 4#30 5#31 6#30 7#31 8#31 9#30 10#31 11#30 12#31") do (
  19.         for /f "tokens=1,2 delims=#" %%i in ("%%a") do set/a LineTemp-=%%j
  20.         set/a month-=1&goto loop1
  21. ))
  22. set /a Day=_%Month%-LineTemp
  23. for /f "usebackq delims=" %%a in ("ab cd.txt") do (
  24.       if !Month! lss 10 (set "Mon=0!Month!") else (set "Mon=!Month!")
  25.       if !Day! lss 10 (set "Da=0!Day!") else (set "Da=!Day!")
  26.       echo !Year!年!Mon!月!Da!日 %%a
  27.       set/a Day+=1
  28.       if !Day! GTR 28 CALL :MonitorMonthCount
  29. )>>c.txt
  30. echo %time%
  31. pause>nul&exit/b
  32. :MonitorMonthCount
  33. if %day% gtr !_%month%! set/a "day=1,month+=1"&echo.
  34. if !month! equ 13 set /a "month=1,year+=1,_2=28+(^!(year%%4)&^!(^!(year%%100)) | ^!(year%%400))"
复制代码
钻了一个空子,用findstr /n /v $ "ab cd.txt"来计算行数,当然最末行不能是空行。
作者: 随风    时间: 2008-10-20 17:00

::递加日期,以处理5万行的文本为例
::本机测试   耗时: 0 小时 0 分钟 14 秒 72 毫秒
::这次测试怎么都要14秒。。郁闷!难道是电脑不同的原因?
代码效率关键是,for 内部运行的命令越少越好。
:
  1. @echo off&setlocal enabledelayedexpansion
  2. set ttime=%time%&set wjm=ab cd.txt
  3. for /f "tokens=2 delims=:" %%a in ('find /v /c "" "%wjm%"') do set /a tian=%%a-1
  4. call :Date2Day "%date:~0,10%" %tian% sy sm sd
  5. echo  %tian% 天前的日期是:%sy%年%sm%月%sd%日
  6. set /a sm+=100,sd+=100,n=100,yue113=131
  7. for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do set /a n+=1&set /a yue!n!=1%%a
  8. set /a yue102="^!(sy%%4)&^!(^!(sy%%100))|^!(sy%%400)+128",py=yue!sm!
  9. echo.1>nul 3>c.txt
  10. for /f "usebackq delims=" %%a in ("%wjm%") do (
  11.    echo !sy!年!sm:~-2!月!sd:~-2!日 %%a
  12.    set /a sd+=1
  13.    if !sd! gtr !py! (
  14.      set /a sd=101,sm+=1&set /a py=yue!sm!&echo.
  15.      if !sm! gtr 112 (
  16.         set /a sy+=1,sm=101,yue102="^!(sy%%4)&^!(^!(sy%%100))|^!(sy%%400)+128"
  17. )))
  18. echo.1>nul 4>con
  19. call :time0 "%ttime%" "%time%" ok
  20. echo  耗时: %ok%&title ok
  21. echo.&pause
  22. start notepad "c.txt"&exit  
  23. :Date2Day 获取指定天数的日期 (封装)
  24. setlocal&rem by Will Sort @cn-dos
  25. for /f "tokens=1-3 delims=/-, " %%a in ('echo/%~1') do (
  26. set /a yy=%%a,mm=100%%b%%100,dd=100%%c%%100)
  27. set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
  28. set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
  29. set /a i=j-%~2,a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
  30. set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
  31. set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
  32. endlocal&set %3=%yy%&set %4=%mm%&set %5=%dd%&goto :EOF
  33. :time0  计算批处理运行时间(封装)
  34. setlocal&set /a n=0&rem by 随风 @bbs.bathome.net
  35. for /f "tokens=1-8 delims=.: " %%a in ("%~1:%~2") do (
  36. set /a n+=10%%a%%100*360000+10%%b%%100*6000+10%%c%%100*100+10%%d%%100
  37. set /a n-=10%%e%%100*360000+10%%f%%100*6000+10%%g%%100*100+10%%h%%100)
  38. set /a s=n/360000,n=n%%360000,f=n/6000,n=n%%6000,m=n/100,n=n%%100
  39. set "ok=%s% 小时 %f% 分钟 %m% 秒 %n% 毫秒"
  40. endlocal&set "%~3=%ok:-=%"&goto :eof
复制代码

[ 本帖最后由 随风 于 2008-10-20 17:04 编辑 ]
作者: pusofalse    时间: 2008-10-20 17:19

简直无敌了,测试随风兄的代码:
作者: 随风    时间: 2008-10-20 17:54

看代码真是累,若想完全看懂各位的代码太需要时间了。
略看了一下,发现大家都忽略了一个问题,就是代码中for循环时你们都用了 call  命令
5万行,即使只运行10分之一次,效率也是会被明显拖慢的。
在庞大的数据面前,即使是 set str=!str:~-2! 这样的语句都会对效率有一定影响。
另外:pusofalse 测试真的是7秒吗?
    我测试最好的都是 13 秒,难道真的和电脑有这么大的关系?
    各位测试的结果也贴出来看看好吗/?

[ 本帖最后由 随风 于 2008-10-20 17:58 编辑 ]
作者: pusofalse    时间: 2008-10-20 18:06

我512M内存,1.6G双核CPU,机器配置也不怎么样。
测试最长的耗时时间正好是8秒。
这次测试结果:
作者: terse    时间: 2008-10-20 22:54


作者: wzyqwdl    时间: 2008-11-5 23:21

2008-11-5号  23:18分左右测试的,
CPU :AMD 双核3800+
内存:2G DDR2

估计剩下的就和操作系统有关了。(我先前用计算π 的软件弄的机器很卡。)
应该和内存没什么关系了吧?
顺便新手来报道下,各位 午夜好。
[attach]1494[/attach]




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2