标题: [文本处理] 批处理如何获取/提取大文本中含有指定字符串的最后一行内容? [打印本页]
作者: iq301 时间: 2015-2-5 18:00 标题: 批处理如何获取/提取大文本中含有指定字符串的最后一行内容?
本帖最后由 pcl_test 于 2017-4-10 13:58 编辑
有个文档每天由服务器生成,文档size非常大,有1G以上。我要找出文档里面符合 Date/Time 的行,并显示最后一行出来.
由于文档太大了。用bat速度好慢,
求助 :由于ISO原因,不允许使用第三方软件。只能自己编程。请问大家有没办法解决?谢谢
文档内容样式:
asdadffdasfsafasfasdfffadsfsafasdf
Date/Time: 2015-02-05 18:05:50
fsdfsadfsdfsdfdf
adfsfsdfasfffdsfafasdf
asdadffdasfsafasfasdfffadsfsafasdf
Date/Time: 2015-02-05 19:05:50
fsdfsadfsdfsdfdf
adfsfsdfasfffdsfafasdf
作者: CrLf 时间: 2015-2-5 20:19
- @echo off
- for /f "delims=" %%a in ('findstr "^Date/Time:" 文档.log') do set DateTime=%%a
- echo 取得的结果为 %DateTime%
- pause
复制代码
作者: iq301 时间: 2015-2-6 05:19
回复 2# CrLf
文本txt档,非常大,用bat非常非常的慢。。bat可能吃不消,请问有没别的语言能达到快速的效果?比如:JAVA C++ VBS 这些语言我都i不会。。
作者: CrLf 时间: 2015-2-6 06:49
什么系统
作者: CrLf 时间: 2015-2-6 06:54
本帖最后由 CrLf 于 2015-2-6 07:33 编辑
试试这样,希望sort 受得了- @echo off
- findstr "^Date/Time:" 文档.log | sort /65535 /o tmp.txt
- set /p DateTime=<tmp.txt
- echo 取得的结果为 %DateTime%
- pause
复制代码
作者: 慕夜蓝化 时间: 2015-2-6 08:17
本帖最后由 慕夜蓝化 于 2015-2-6 17:14 编辑
原来是要取得最后一行的吗 = =- @echo off
- type "a.txt"|find "Date/Time" >$
- for /f "delims=" %%i in ('type "$"^|find /v /c ""') do (
- set/a n=%%i-1
- )
- for /f "skip=%n% delims=" %%a in ('type "$"') do (
- echo,%%a
- )
- del /f/q "$"
- pause
复制代码
作者: terse 时间: 2015-2-6 11:21
- @if(0)==(0) echo off
- cscript -nologo -e:jscript %0 <d.txt
- pause & exit/b
- @end
- var text = WScript.StdIn.ReadAll();
- var f = text.match(/Date\/Time:.*/ig);
- if (f) {WSH.Echo(f[f.length - 1])}
复制代码
作者: CrLf 时间: 2015-2-6 11:44
回复 7# terse
感觉像 js 和 powershell 这种所有字符串都是对象的语言处理大文件的消耗应该很大,猜过去用 vbs 的 instrRev 也许更快
火车上,没法验证,哪位有兴趣做个实验?挺好奇的
作者: Demon 时间: 2015-2-6 13:06
1G ReadAll
作者: CrLf 时间: 2015-2-6 16:08
改用 ReadLine(10000) 应该就不怕占内存了
作者: terse 时间: 2015-2-6 18:12
回复 8# CrLf
试了 POWERSHELL 方案 没测试大文件
测试一 110MB 文件 效率比JS略高
等楼主测试吧- $file = "c:d.txt"
- ([io.file]::ReadAllLines($file) -match "Date/Time:")[-1]
复制代码
作者: CrLf 时间: 2015-2-6 19:19
本帖最后由 CrLf 于 2015-2-6 19:54 编辑
回复 11# terse
用顶楼数据生成了 468M 大小的文件做了一组测试,结果让我大跌眼镜,gawk 和 sed 竟然这么慢
gawk 耗时58.6s,内存占用可忽略不计- @echo off
- set t=%time%
- gawk "/^Date\/Time:/{$a=$0}END{print $a}" tmp.txt
- echo %t% %time%
- pause
复制代码
sed 耗时未知(太久了,等不起),内存占用可忽略不计- @echo off
- set t=%time%
- sed -n "/^Date\/Time:/h;${g;p}" tmp.txt
- echo %t% %time%
- pause
复制代码
find /c + skip 耗时79.7s,内存占用可忽略不计- @echo off
- set t=%time%
- find "Date/Time:"<tmp.txt>$
- for /f %%a in ('find /c /v ""^<$') do set /a n=%%a-1
- for /f "skip=%n% delims=" %%a in ($) do echo %%a
- echo %t% %time%
- pause
复制代码
sort + set /p 耗时24.7s,内存占用中等- @echo off
- set t=%time%
- findstr "^Date\/Time:" tmp.txt | sort /+65535 /o tmp2.txt
- set /p DateTime=<tmp2.txt
- echo 取得的结果为 %DateTime%
- echo %t% %time%
- pause
复制代码
bat + js 耗时29.5s,内存占用高(约是文件体积的五倍)- @if(0)==(0) echo off
- set t=%time%
- cscript -nologo -e:jscript %0 <tmp.txt
- echo %t% %time%
- pause & exit/b
- @end
- var text = WScript.StdIn.ReadAll();
- var f = text.match(/Date\/Time:.*/ig);
- if (f) {WSH.Echo(f[f.length - 1])}
复制代码
纯 js 耗时65.26s,内存占用高(约是文件体积的两倍)- var start = new Date()
-
- var fso = new ActiveXObject('Scripting.FileSystemObject')
- var ts = fso.OpenTextFile('tmp.txt',1)
-
- var text = ts.ReadAll()
- var f = text.match(/Date\/Time:.*/ig);
- if (f) {WSH.Echo(f[f.length - 1])}
-
- var end = new Date()
- WSH.Echo((end - start)/1000)
复制代码
纯 vbs 耗时49.354s,内存占用高(约是文件体积的两倍,和 js 相当)- start = timer
-
- Set fso = CreateObject("Scripting.FileSystemObject")
- Set ts = fso.OpenTextFile("tmp.txt",1)
-
- text = ts.ReadAll
- i = instrRev(text,vbLf & "Date/Time:")
- text = mid(text,i)
- text = split(text,vbCrLf)(0)
-
- end2 = timer
-
- WSH.Echo(text & vbcrlf & (end2 - start))
复制代码
powershell io.file::ReadAllLines 耗时29.6s,内存占用高(约是文件体积的五倍)- $start = get-date
- $file = "C:\Users\Administrator\Desktop\tmp.txt"
- ([io.file]::ReadAllLines($file) -match "Date/Time:")[-1]
-
- $end = get-date
- $end - $start
复制代码
powershell select-string 耗时140.8s,内存占用高(约是文件体积的五倍)- $start = get-date
- $file = "C:\Users\Administrator\Desktop\tmp.txt"
- $a = select-string $file -pattern '^Date/Time:'
- $a[-1]
- $end = get-date
- $end - $start
复制代码
js while+Read 耗时22.675s,内存占用低,但本质是对最后 100000~200000 个字节进行搜索,所以...- var start = new Date()
-
- var fso = new ActiveXObject('Scripting.FileSystemObject')
- var ts = fso.OpenTextFile('tmp.txt',1)
- var arr = ['','']
- var i=0
-
- while(!ts.AtEndOfStream){
- arr[i=!i]=ts.Read(100000)
- }
-
- var f = (arr[!i]+arr[i]).match(/Date\/Time:.*/ig);
- var end = new Date()
- if (f) {WSH.Echo(f[f.length - 1])}
-
- WSH.Echo((end - start)/1000)
复制代码
改用 skip 实现只取最后的 10000 字节,耗时21.96s,内存占用低,缺点和前一个方法一样,为了效率,并非全文搜索- var start = new Date()
-
- var fso = new ActiveXObject('Scripting.FileSystemObject')
- var file = fso.GetFile('tmp.txt')
- var ts = file.OpenAsTextStream(1)
-
- var skip = file.Size-10000
- if(skip>0)ts.Skip(skip)
-
- var text = ts.ReadAll()
-
- var f = text.match(/Date\/Time:.*/ig);
- var end = new Date()
- if (f) {WSH.Echo(f[f.length - 1])}
-
- WSH.Echo((end - start)/1000)
复制代码
作者: iq301 时间: 2015-2-6 20:15
各位亲,非常谢谢你们无私的帮助,原文件行数超过30W行。这样的约1.5G文本有10个。操作系统是WIN7 。如果占用内存太大,电脑会不会直接挂掉。。。
作者: caruko 时间: 2015-2-11 15:00
建议用C写个程序,用 fseek 将位置指针从最后往前移动,读取指定长度的字符对比,直到找到符合的 字符。
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |