Board logo

标题: [文本处理] 批处理怎样提高字串替换速度? [打印本页]

作者: Topgunguy    时间: 2012-7-26 23:18     标题: 批处理怎样提高字串替换速度?

各位版友大家好,我想请教有关替换字串的问题,
以下这段程式码可以替换字串
  1. @ECHO OFF
  2. (for /f "tokens=1* delims=:" %%i in ('findstr /n .* %1') do (
  3. set "line=%%j"
  4. setlocal enabledelayedexpansion
  5. if "!line!"=="" (echo.!line!) else (
  6. set "line=!line:H1=H2!"
  7. echo.!line!
  8. endlocal
  9. )))>back.txt
  10. move back.txt %1
复制代码
只是这样一行一行地echo,档案超过50kb,就会开始lag,档案越大,lag越久。

如果要处理的替换只有前二十行和後十行,
请问将文本分成三区来处理会不会比较快呢?

先将A区前二十行替换完毕,
不会动到的B区用>输出到A区後面,
最後十行C区放B区後。

所以我想请问读取文本的前二十行就跳出回圈应该要怎麽写呢?
findstr /n [1-20] %1
会跑出奇怪的结果
作者: forfiles    时间: 2012-7-27 06:53

用sed或者gawk之类的会比较快
作者: canyuexiaolang    时间: 2012-7-27 07:51

  1. @ECHO OFF & setlocal enabledelayedexpansion
  2. (for /f "tokens=1* delims=:" %%i in ('findstr /n .* %1') do (
  3.     set "line=%%j"
  4.     if not "!line!"=="" (set "line=!line:H1=H2!")
  5.     echo.!line!
  6. ))>back.txt
  7. move back.txt %1
复制代码
可以简化。(setlocal移到外面不好但是为了效率移出去..)
作者: CrLf    时间: 2012-7-27 10:02

将 echo.!line! 改为 echo:!line! 能稍微提高效率,另外
  1. set "line=!line:H1=H2!"
  2. echo.!line!
复制代码
因为此时line必然不为空,所以可以简化成:
  1. echo:!line:H1=H2!
复制代码

作者: Demon    时间: 2012-7-27 12:23

将 echo.!line! 改为 echo:!line! 能稍微提高效率,另外因为此时line必然不为空,所以可以简化成:
CrLf 发表于 2012-7-27 10:02


遗憾的是,echo:并不比echo.更高效,它们的处理方式是一样的。
作者: CrLf    时间: 2012-7-27 14:15

回复 5# Demon


    "." 会额外触发对文件名的匹配,参考:http://bbs.bathome.net/viewthread.php?tid=4831
作者: Demon    时间: 2012-7-27 15:12

本帖最后由 Demon 于 2012-7-27 15:14 编辑
回复  Demon


    "." 会额外触发对文件名的匹配,参考:
CrLf 发表于 2012-7-27 14:15


CMD对echo. echo: echo\的处理过程是一样的。

[attach]5544[/attach]

如果在命令中发现.:\,并且CMD拓展是开启的话,就会调用GetFileAttributes函数获取文件的属性,如果文件不存在或者文件是目录的话,那么就会把.:\改成NUL;否则会当成外部命令。

[attach]5545[/attach]

但是GetFileAttributes有个BUG,会把echo.当成是echo,所以如果存在以echo为名称的文件的话,GetFileAttributes会认为echo.文件是存在的,然后CMD把echo.当成外部命令,就会导致错误。
  1. cd .>echo
  2. echo.
  3. pause
复制代码
'echo.' is not recognized as an internal or external command, operable program or batch file.
  1. md echo
  2. echo.
  3. pause
复制代码
没有问题
  1. cd .>echo
  2. setlocal disableextensions
  3. echo.
  4. pause
复制代码
没有问题

在不存在echo文件或者文件夹的情况下echo. echo: echo/的处理是一样的,不存在哪个效率更高的问题;存在echo文件的话echo.会导致错误,更不存在效率问题了。

考虑效率的话,echo, echo; echo=稍微好一些(其实也就少调用了一次GetFileAttributes)。
作者: CrLf    时间: 2012-7-27 16:18

本帖最后由 CrLf 于 2012-7-27 16:19 编辑

回复 7# Demon


   
噢!这倒没想到,测试结果也确实如此,感谢指正。
不过 echo, echo; echo= 的缺陷在于无法处理 echo;/? 这种参数为 /? 的情况,因为它们都是默认分隔符
这样一来,echo[ 和 echo] 应该是既保证通用性又能避免降低效率的方案了吧
作者: Demon    时间: 2012-7-27 16:36

回复  Demon


   
噢!这倒没想到,测试结果也确实如此,感谢指正。
不过 echo, echo; echo= 的缺陷 ...
CrLf 发表于 2012-7-27 16:18

在我这里是没有问题的。
作者: forfiles    时间: 2012-7-27 16:40

回复 8# CrLf


这里的测试有问题吗?
http://www.bathome.net/thread-4482-1-1.html
作者: CrLf    时间: 2012-7-27 16:48

回复 9# Demon


    试试 echo;/? 和 echo[/?,win7 下测试是有区别的

回复 10# forfiles


    没有什么问题啊,只是那帖子讨论的只是效率,而我们希望找到一个兼顾效率与通用性的方案
作者: forfiles    时间: 2012-7-27 16:51

回复 11# CrLf



7楼说:echo. echo: echo/的处理是一样的,不存在哪个效率更高的问题
8楼说:测试结果也确实如此
作者: Demon    时间: 2012-7-27 17:03

回复  Demon


    试试 echo;/? 和 echo[/?,win7 下测试是有区别的

回复  forfiles


    没有 ...
CrLf 发表于 2012-7-27 16:48


哦,理解错了。
作者: CrLf    时间: 2012-7-27 17:13

回复 12# forfiles


    测试代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. for %%a in (. : \ ";" "[") do (
  3. echo !time!
  4. echo echo%%~a
  5. (for /l %%b in (1 1 10000) do echo%%~a)>nul
  6. )
  7. echo !time!
  8. pause
复制代码

作者: Topgunguy    时间: 2012-10-2 19:53

如果要处理的替换只有前二十行和後十行,
请问将文本分成三区来处理会不会比较快呢?

先将A区前二十行替换完毕,
不会动到的B区用>输出到A区後面,
最後十行C区放B区後。


这样做超快,但超过1mb,批处理会当掉,
  1. @echo off
  2. @setlocal enabledelayedexpansion
  3. del *.txt
  4. echo %1>drive.txt
  5. (for /f "tokens=1* delims=:" %%d in ('findstr /n .* drive.txt') do (
  6. set drive=%%e"
  7. set drive=!drive:~0,2!
  8. ))
  9. (for %%f in (%*) do (
  10. call echo !drive!%%%%f
  11. )>>t1.txt)
  12. ECHO\1.HassM09 2.HassM09T 3.HassM09TOM99 4. 5.HG83
  13. ECHO\11.M09 12.M09T 13.M09TOM99 16.M8M09  18.M57
  14. set /p prog="prog is "
  15. if %prog% equ 3 (call D:\LGetCode\TransCode\HassM09TOM99.bat) else (
  16. echo\ no mode
  17. )
  18. PAUSE
  19. del *.txt
  20. del *.doc
复制代码
HassM09TOM99.bat
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=1* delims=:" %%g in ('findstr /n .* t1.txt') do (
  4. set "file=%%h"
  5. ECHO]************************************
  6. echo]starting %%h
  7. setlocal enabledelayedexpansion
  8. set "tool=%%h"
  9. set "tool=!tool:~-4,1!"
  10. set "dec=!file:~-5,1!"
  11. if !dec! gtr 9 set dec=0
  12. set num=!dec!!tool!
  13. rem *******
  14. rem First20Line
  15. rem *******
  16. echo]First20
  17.     (for /l %%a in (1 1 20) do (
  18.        set str=&set /p str=
  19.        echo]!str!
  20.     ))<%%h >First20.txt
  21. REM ***************************************************
  22. REM deal First20Line
  23. REM ***************************************************
  24. echo]dealFirst20
  25. (for /f "tokens=1* delims=:" %%i in ('findstr /n .* First20.txt') do (
  26.     set "line=%%j"
  27.     setlocal enabledelayedexpansion
  28.     if "!line!"=="" (echo\!line!) else (
  29.    for %%n in (!num!) do set "line=!line:O1000=O00%%n!"
  30.    for %%n in (!num!) do set "line=!line:O0100=O00%%n!"
  31.    for %%n in (!num!) do set "line=!line:O0001=O00%%n!"
  32.     for %%m in (!tool!) do set "line=!line:(SC POSTPROCESSOR A.I.C TAICHUNG)=T%%mM6!"
  33.      set "line=!line:/G05.1 Q1= !"
  34.     set "line=!line:.M09=.!"
  35.     for %%l in (!tool!) do set "line=!line:H1=H%%l!"
  36.     echo\!line!
  37. endlocal
  38. )))>back.txt
  39. move back.txt First20.txt
  40. rem ********
  41. rem delFirst20
  42. rem ********
  43. more +20 %%h>WithoutFirst20.txt
  44. findstr .* WithoutFirst20.txt >> First20.txt
  45. rem *********************************************************
  46. rem Last20Line
  47. rem *********************************************************
  48. echo]last20line
  49.     sort /+4096 First20.txt /o Reverse.txt
  50.     (for /l %%a in (1 1 20) do (
  51.        set str=&set /p str=
  52.        echo]!str!
  53.     ))<Reverse.txt >Last20Rev.txt
  54.     sort /+4096 Last20Rev.txt /o Last20.txt
  55. (for /f "tokens=1* delims=:" %%i in ('findstr /n .* Last20.txt') do (
  56.     set "line=%%j"
  57.     setlocal enabledelayedexpansion
  58.     if "!line!"=="" (echo\!line!) else (
  59.     set "line=!line:/G05.1 Q0= !"
  60.     set "line=!line:M30=M99!"
  61.     echo\!line!
  62. endlocal
  63. )))>back.txt
  64. move back.txt Last20.txt
  65. rem *******
  66. rem delLast20Line
  67. rem *******
  68. ECHO]delLast20Line
  69. sort /+4096 First20.txt /o ABrev.txt
  70. more +20 ABrev.txt>WithoutCrev.txt
  71. sort /+4096 WithoutCrev.txt /o WithoutC.txt
  72. findstr .* Last20.txt >> WithoutC.txt
  73. move WithoutC.txt %%h
  74. rem ********
  75. rem End Main Loop Do and For
  76. rem ********
  77. echo]%%h is done
  78. ))
复制代码





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