Board logo

标题: 比较批处理中for、findstr、与sed命令进行文本内容匹配速度测试 [打印本页]

作者: nh_wzg    时间: 2008-10-11 16:38     标题: 比较批处理中for、findstr、与sed命令进行文本内容匹配速度测试

【环境】
os:win2k en server
dos窗口:cmd.exe
for命令:系统自带
findstr命令:系统自带
gnu_sed命令:v4.14
super_sed命令:v3.62 (based on gnu_sed v4.1)
【附件】
fi20.bat:for/f命令批处理
fi21.bat:findstr命令批处理
fi22.bat:sed命令批处理
fi23.bat:ssed命令批处理
批处理均使用cadv作为参数执行,即:fi20.bat cadv
cadvfi25.log:批处理调用的数据文件
cadvfi21.csv:批处理调用的数据文件
cadvfi25_t.log:内容与cadvfi25.log基本一致,仅“\”改为“\\”,供findstr,sed调用。
cadvfi23.csv:批处理进行文本匹配生成的数据文件。
cadvfi23.csv_for:与各比较命令批处理相对应的结果数据文件,供检验正确性用。
cadvfi23.csv_findstr:与各比较命令批处理相对应的结果数据文件,供检验正确性用。
cadvfi23.csv_sed:与各比较命令批处理相对应的结果数据文件,供检验正确性用。
cadvfi23.csv_ssed:与各比较命令批处理相对应的结果数据文件,供检验正确性用。
【目的】
比较for命令,findstr命令,与sed命令对文本内容进行匹配的速度,从而择优选用与学习。
【测试方式】
对于相同的内容分别测试上述三个命令进行文本匹配的速度三次,取平均值。
使用for命令的测试批处理:
  1. REM 测试文件匹配的方式与速度
  2. REM Date:[2008-10-11 14:27:52]  Author:nh_wzg
  3. :BEGIN
  4. ::File notes...
  5. @echo off
  6. cls&echo.
  7. Title [For command in the match operation]
  8. echo [For command in the match operation]
  9. :INIT
  10. echo [批处理执行初始化(Batch Initializing...)]
  11. echo.
  12. set t=%time%
  13. :MATCH
  14. set /p =[匹配压缩文件与解压文件信息的对应关系并输出 ... <nul
  15. echo md51,fullpath_filename,path,fullname1,fullname2,md52,name2,ext2,size2,ts2,tu,tc,>%1fi23.csv
  16. setlocal enabledelayedexpansion
  17. for /f "skip=2 tokens=2,4 delims= " %%l in (%1fi25.log) do (
  18.     set v1=%%l
  19.     for /f "skip=1 tokens=1-11 delims=," %%a in (%1fi21.csv) do (
  20.         if /i %%l==%%b (
  21.         set aa=%%a
  22.         set bb=%%b
  23.         set cc=%%c
  24.         set dd=%%d
  25.         REM ----------------------------------------------------------------------
  26.         REM findstr /v /c:%%b %1tfi21.csv >t21.csv
  27.         REM move /y t21.csv %1tfi21.csv
  28.         REM ----------------------------------------------------------------------
  29.         )
  30.     )
  31.     echo !aa!,!bb!,!cc!,!dd!,>>%1fi23.csv
  32.     set aa=
  33.     set bb=
  34.     set cc=
  35.     set dd=
  36. )
  37. endlocal
  38. set /p =Done!]<nul
  39. echo.
  40. echo.
  41. echo Command start: %t%
  42. echo Command   end: %time%
  43. echo.
  44. echo.
  45. :END
  46. pause::[Press Any Key to Exit...]&echo.
复制代码
使用findstr命令的测试批处理:
  1. REM 测试文件匹配的方式与速度
  2. REM Date:[2008-10-11 14:55:39]  Author:nh_wzg
  3. :BEGIN
  4. ::File notes...
  5. @echo off
  6. cls&echo.
  7. Title [Findstr command in the match operation]
  8. echo [Findstr command in the match operation]
  9. echo.
  10. :INIT
  11. echo [批处理执行初始化(Batch Initializing...)]
  12. echo.
  13. set t=%time%
  14. :MATCH
  15. set /p =[匹配压缩文件与解压文件信息的对应关系并输出 ... <nul
  16. echo md51,fullpath_filename,path,fullname1,fullname2,md52,name2,ext2,size2,ts2,tu,tc,>%1fi23.csv
  17. setlocal enabledelayedexpansion
  18. for /f "skip=2 tokens=2,4 delims= " %%l in (%1fi25_t.log) do (
  19.     set v1=%%l
  20.     for /f "usebackq tokens=1-11 delims=," %%a in (`findstr /i "%%l" %1fi21.csv`) do (
  21.         set aa=%%a
  22.         set bb=%%b
  23.         set cc=%%c
  24.         set dd=%%d
  25.         REM ----------------------------------------------------------------------
  26.         REM findstr /v /c:%%b %1tfi21.csv >t21.csv
  27.         REM move /y t21.csv %1tfi21.csv
  28.         REM ----------------------------------------------------------------------
  29.     )
  30.     echo !aa!,!bb!,!cc!,!dd!,>>%1fi23.csv
  31.     set aa=
  32.     set bb=
  33.     set cc=
  34.     set dd=
  35. )
  36. endlocal
  37. set /p =Done!]<nul
  38. echo.
  39. echo.
  40. echo Command start: %t%
  41. echo Command   end: %time%
  42. echo.
  43. echo.
  44. :END
  45. pause::[Press Any Key to Exit...]&echo.
复制代码
使用sed命令的测试批处理:
  1. REM 测试文件匹配的方式与速度
  2. REM Date:[2008-10-11 14:55:39]  Author:nh_wzg
  3. :BEGIN
  4. ::File notes...
  5. @echo off
  6. cls&echo.
  7. Title [GNU_sed v4.14 command in the match operation]
  8. echo [GNU_sed v4.14 command in the match operation]
  9. echo.
  10. :INIT
  11. echo [批处理执行初始化(Batch Initializing...)]
  12. echo.
  13. set t=%time%
  14. :MATCH
  15. set /p =[匹配压缩文件与解压文件信息的对应关系并输出 ... <nul
  16. echo md51,fullpath_filename,path,fullname1,fullname2,md52,name2,ext2,size2,ts2,tu,tc,>%1fi23.csv
  17. setlocal enabledelayedexpansion
  18. for /f "skip=2 tokens=2,4 delims= " %%l in (%1fi25_t.log) do (
  19.     set v1=%%l
  20.     for /f "usebackq tokens=1-11 delims=," %%a in (`sed -n "/%%l,/Ip" %1fi21.csv`) do (
  21.         set aa=%%a
  22.         set bb=%%b
  23.         set cc=%%c
  24.         set dd=%%d
  25.         REM ----------------------------------------------------------------------
  26.         REM findstr /v /c:%%b %1tfi21.csv >t21.csv
  27.         REM move /y t21.csv %1tfi21.csv
  28.         REM ----------------------------------------------------------------------
  29.     )
  30.     echo !aa!,!bb!,!cc!,!dd!,>>%1fi23.csv
  31.     set aa=
  32.     set bb=
  33.     set cc=
  34.     set dd=
  35. )
  36. endlocal
  37. set /p =Done!]<nul
  38. echo.
  39. echo.
  40. echo Command start: %t%
  41. echo Command   end: %time%
  42. echo.
  43. echo.
  44. :END
  45. pause::[Press Any Key to Exit...]&echo.
复制代码
【结果】
在我的机器上面的测试的结果是:findstr(2.95s)》gnu_sed(8.08s)》for /f(8.21s),结果对功能超强的gnu_sed来说,不免会让人失去学习的动力。但是如果对使用sed的批处理稍作修改,使用super_sed v3.62(ssed.exe),结果是惊人的ssed(1.19s)。
可见在一般的情况下面,使用findstr是比较方便的,不仅因为它快,还因为它是随系统自带的。
但sed也值得我们去仔细学习一下,功能太多了,但是为了速度,也许我们要对它的版本作个选择。

[ 本帖最后由 nh_wzg 于 2008-10-11 17:53 编辑 ]
作者: nh_wzg    时间: 2008-10-11 16:44

需要附件的朋友请下载:
http://www.namipan.com/d/e2f7f70 ... 4260e78751026e80300

[ 本帖最后由 Batcher 于 2009-5-16 12:57 编辑 ]
作者: qq641255849    时间: 2008-10-11 16:51

颇强大,试下先
作者: qq641255849    时间: 2008-10-11 16:58

[匹配压缩文件与解压文件信息的对应关系并输出 ... 系统找不到文件 fi25.log。
Done!]
什么意思?
作者: pusofalse    时间: 2008-10-11 17:27

用最合适的代码做最合适的事情吧。
另,同遇到6楼的问题。
作者: nh_wzg    时间: 2008-10-11 17:56

不好意思,因为这个比较是从我的一个测试中临时抽出来的,原贴没有对批处理的参数加以颜色,大小强调,要加一个“cadv”参数在每个批处理的后面。
作者: pusofalse    时间: 2008-10-11 18:13

总觉得sed的效率如此低下有点不可思议,应该是配合了for在使用。
只用sed的正则表达式,完全可以匹配出想要的内容。
作者: yslyxqysl    时间: 2008-10-11 18:28     标题: 回复 3楼 的帖子

请将3个附件发在同一帖内或三个文件压成一个rar文件。
作者: pusofalse    时间: 2008-10-11 18:41

  1. @echo off
  2. echo %time%
  3. sed -e "/d:\\dos\\temp\\I386\\0[0-9A-Z]\{3\}/!d" -e "s/^,//" -e "s/\(CS_,\)[0-9A-Z]\{4\}.*/\1/" "cadvfi21.csv">test
  4. start notepad.exe test
  5. echo %time%
  6. pause
复制代码
初学sed,很繁杂,但测试用时能控制在0.5s之内。
作者: nh_wzg    时间: 2008-10-11 19:13

原帖由 yslyxqysl 于 2008-10-11 18:28 发表
请将3个附件发在同一帖内或三个文件压成一个rar文件。

因为还不熟悉论坛,不知道一个帖子内可以上传几个接近100k的附件。试看是否能够改正。
作者: nh_wzg    时间: 2008-10-11 19:26

原帖由 pusofalse 于 2008-10-11 18:41 发表
@echo off
echo %time%
sed -e "/d:\\dos\\temp\\I386\\0[0-9A-Z]\{3\}/!d" -e "s/^,//" -e "s/\(CS_,\)[0-9A-Z]\{4\}.*/\1/" "cadvfi21.csv">test
start notepad.exe test
echo %time%
pause初学sed,很繁杂, ...


因为原来的测试中要由一个LOG文件提取文件名数据,再根据提取的文件名取得相关数据,再合成一个相互对应的数据文件,以我现在的水平,只能够使用FOR+SED/FINDSTR来实现。

另外就是想提供一个我环境下面的数据,我认为在例子的环境下面,大家的条件是基本一样的,仅测这一匹配操作的速度来比较。
作者: Batcher    时间: 2008-10-11 21:46

我们可以拿拳头去打蚊子,也可以用蚊香去薰蚊子。
但我们不能因为前者的灭蚊效果比不上后者,就说拳头不如蚊香好。
sed亦然。
作者: 随风    时间: 2008-10-12 01:39

呵呵,又是效率的话题。!
我说两句。。
首先,我不同意楼主的说的 sed 效率低下。
楼主的测试代码只能说是在批处理中频繁调用外部命令会使批处理运行效率低。而不是命令本身效率低。
关于此话题在我的另一帖中曾讨论过
http://bbs.bathome.net/thread-2089-1-1.html

如果楼主想证实的是这三个命令“匹配文本的速度”那么你的代码不能说明什么。
而应该是用以下的方式测试。

以大小为 2.22m 的a.txt文件为测试样本。
以下三句代码都是匹配 a.txt 中以 ok 开头的行,速度都是快的惊人!
  1. for /f "delims= " %%a in (a.txt) do if "%%a"=="ok" echo %%a
  2. findstr "^ok" a.txt
  3. sed -n "/^ok/p" a.txt
  4. pause
复制代码
但功能却各有不同,
for 虽说速度也快,但受特殊字符的限制,且若是需要对每行都进行处理时速度是不及sed之万一的。
findstr 可以匹配指定的行,但无法对其进行处理,且匹配的局限性很大。
而sed 是有名的文本流编辑器,以功能强大和高效著称。可以匹配各种自定义条件的行并对其进行处理。
5楼说的好, 用最合适的代码做最合适的事。

楼主不防试试分别用 for 和 sed 给文档每行开头都加一个字符串,看看谁更快?
或是替换每行的指定字符串?
或是给文档的第某行至某行的字符串进行替换?

sed 效率并不慢,只是楼主的使用方法不当而以。。(仅对顶楼测试代码而言)

[ 本帖最后由 随风 于 2008-10-12 01:50 编辑 ]
作者: nh_wzg    时间: 2008-10-12 07:49

各位老大都给了深入的指点,在下受教学习了。
谢谢!!
作者: bjydfq    时间: 2009-6-1 16:29

学习了。。。谢谢楼主及各位大大
作者: 我来了    时间: 2016-12-15 12:41

测试样本太小了
最好找IDA生成的文件做测试才更有说服力。




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