批处理去除超大文本中的重复行

批处理去除超大文本中的重复行
去除超大文本中的重复行
在非常批处理论坛看到这个题,觉得挺有挑战的,上百万行的数据,光靠批处理应该是难做到了,不知道借助第三方命令行工具能否完成。

文本内有大概100W行的数据
要求一、 删除所有重复行
要求二、 以----为分隔符,将第一列与第二列重复的行删除(描述有问题,以末尾的红色字更新为准)
两个要求完成一个也行,分两个代码完成也行,最完美的是在一个代码中完成两个要求。

部分样本
引用:
12779----alibaba140379----222.222.222.222----哈哈哈哈哈哈----2008-5-20----21:24:20
13166----BXGHgxst115----123.112.68.25----欧洲
12779----alibaba140379----203.93.208.138----山东省青岛市网通----2008-5-20----21:24:20
13166----BXGHgxst115----111.111.111.111
12779----alibaba140379----222.222.222.222----哈哈哈哈哈哈----2008-5-20----21:24:20
255004----dsfdsfdsf----123.112.77.25
扩展要求:保持原文本中不重复的行顺序不变

创建 100万 行左右的测试文件代码。
。。。
复制内容到剪贴板
代码:
@echo off&setlocal enabledelayedexpansion
echo 正在创建测试文件 y1.txt 请稍候。。。 行数为 1000005 行
(for /l %%a in (1 1 100) do echo !random!----!random!----!random!!random!----!random!)>y1.txt
(for /l %%a in (1 1 10) do type y1.txt)>y2.txt
(for /l %%a in (1 1 10) do type y2.txt)>y1.txt
(for /l %%a in (1 1 10) do type y1.txt)>y2.txt
(for /l %%a in (1 1 10) do type y2.txt)>y1.txt
(echo !random!----!random!----!random!!random!----!random!!random!
echo !random!----!random!----!random!!random!----!random!!random!
echo !random!----!random!----!random!!random!----!random!!random!
echo !random!----!random!----!random!!random!----!random!!random!
echo !random!----!random!----!random!!random!----!random!!random!)>>y1.txt
del /q y2.txt
问题二描述有问题,现更新
要求二、 以----为分隔符,将第一列与第二列重复的行删除,保留第一行。
比如:
1234---555--44444444444
1234---7777--fafjaf
1234---555--444444
334----7898----dfadifaf
1234---555--00000000000000
这种情况下就保留第1、2、4行
因为第1行、第3行、第5行,的第1列和第2列是重复的。

[ 本帖最后由 随风 于 2009-5-29 17:59 编辑 ]
 
处理6W行记录花了2分多钟,100W就不敢试了!大概要一个多小时吧!
源文件为:sour2.txt
处理结果为:temp3.txt
可完成两个要求。
复制内容到剪贴板
代码:
@echo off&setlocal enabledelayedexpansion
(for /f "delims=" %%a in (sour2.txt) do (
        set/a n+=1
        set num=000000!n!
        echo !num:~-7!-%%a
))>temp.txt
::加入序号保持原来的顺序

(for /f "tokens=1,2,3* delims=-" %%a in ('sort temp.txt /+8') do (
        if "%%b-%%c" neq "!var!" (echo %%a-%%b-%%c-%%d)
        set var=%%b-%%c
))>temp2.txt
::从第8位开始排序,即只按原来的数据排序,重复的丢弃

(for /f "tokens=1,2,3* delims=-" %%a in ('sort temp2.txt') do (
echo %%b----%%c----%%d
))>temp3.txt
::恢复原来的顺序,并丢弃加入的临时序号
把楼主的数据存为sour.txt, 通过下面代码生成的sour2.txt具有6W行记录。
复制内容到剪贴板
代码:

@echo off
(for /f "delims=" %%a in (sour.txt) do (
for /l %%b in (1,1,10000) do (echo %%a)
))>sour2.txt
 
 
 
C:\Test>test.bat
0 小时 0 分钟 1 秒 51 毫秒

C:\Test>type test.bat
@echo off
set begin=%time%
gawk "!a[$0]++" y3.txt>>a.txt
call :time0 %begin% %time% duration
echo %duration%
goto :eof

:time0
::计算时间差(封装)
@echo off&setlocal&set /a n=0&rem code 随风 @bbs.bathome.net
for /f "tokens=1-8 delims=.: " %%a in ("%~1:%~2") do (
set /a n+=10%%a%%100*360000+10%%b%%100*6000+10%%c%%100*100+10%%d%%100
set /a n-=10%%e%%100*360000+10%%f%%100*6000+10%%g%%100*100+10%%h%%100)
set /a s=n/360000,n=n%%360000,f=n/6000,n=n%%6000,m=n/100,n=n%%100
set "ok=%s% 小时 %f% 分钟 %m% 秒 %n% 毫秒"
endlocal&set %~3=%ok:-=%&goto :EOF

 

 

 

@echo off
for /f "delims=" %%i in (test.txt) do (
    i
@echo off
for /f "delims=" %%i in (test.txt) do (
    if not defined %%i set %%i=s & echo %%i>>result.txt)
大概需要30 s就可以了
可是这段代码我有点不理解 不知LS的道能否解释下
f not defined %%i set %%i=s & echo %%i>>result.txt)
大概需要30 s就可以了
可是这段代码我有点不理解 不知LS的道能否解释下
 
 
 
如果要处理的字符没有双引号(有双引号时借助sed先用特殊字符比如中文下的特殊字符,这个花不了到少时间)
新打开一个命令行然后:
免费内容:
for /f "eol= delim=" %a in (tmp.txt)do @if not defined "%a" (@echo.%a>>your.txt&set "%%a=1")
echo.  >>file 的效率大概是每秒5000次,那么100万行需要200秒左右
引用:
原帖由 Kiming 于 2009-5-29 20:42 发表
@echo off
for /f "delims=" %%i in (test.txt) do (
    if not defined %%i set %%i=s & echo %%i>>result.txt)
大概需要30 s就可以了
可是这段代码我有点不理解 不知LS的道能否解释下

if not defined %%i set %%i=s
这句就是保证单行输出的
当一个行第一次出现时,输出后给他一个赋值(随便什么数字都型),当下次它再次出现时,因为有上次的set ...=s
所以已经是"defined"了,自然后面的echo %%i>>result.txt就不会执行了

你把 if not defined %%i set %%i=s & echo %%i>>result.txt改成

if not defined %%i (echo %%i>>result.txt&set %%i=s ) 就容易理解了(注意加上括号)

但是这个代码有bug的,上楼就没有bug了
对于开头行是;还有行内含有空格,特殊字符的<>|等的行
for /f "eol= delim=" %a in (tmp.txt)do @if not defined "%a" @(echo.%a>>your.txt&set "%a=1")
都可以解决

代码:

gawk "BEGIN {FS=\"-\"} !a[$1 $2]++" y1.TXT>y2.txt测试代码这样的

复制内容到剪贴板
代码:
@echo off&setlocal enabledelayedexpansion
echo 正在创建测试文件 y1.txt 请稍候
for /l %%a in (1 1 1000) do (
(for /l %%a in (1 1 2001) do echo !random!!random!!random!----!random!!random!!random!----!random!----!random!!)>>y1.txt
(for /l %%a in (1 1 1001) do echo %random%----%random%----!random!!random!!random!----!random!!random!!random!)>>y1.txt
)

生成150MB左右的Y1文件
处理后 Y2文件 近100MB 左右
处理时间 13.5秒


代码:
gawk "BEGIN {FS=\"-\"} !a[$1 $2]++" y1.TXT>y2.txt测试代码这样的
复制内容到剪贴板
代码:
@echo off&setlocal enabledelayedexpansion
echo 正在创建测试文件 y1.txt 请稍候
for /l %%a in (1 1 1000) do (
(for /l %%a in (1 1 2001) do echo !random!!random!!random!----!random!!random!!random!----!random!----!random!!)>>y1.txt
(for /l %%a in (1 1 1001) do echo %random%----%random%----!random!!random!!random!----!random!!random!!random!)>>y1.txt
)
生成150MB左右的Y1文件
处理后 Y2文件 近100MB 左右
处理时间 13.5秒

、随便等于什么都可以,但是为了减少内存占用量,越短越好。

2、批处理for语句中tokens=*和delims=的区别是什么?
http://bbs.bathome.net/viewthread.php?tid=1654#pid8870
 
 
微软 脚本专家
如何从文本文件中删除所有重复行?
http://www.microsoft.com/china/technet/community/scriptcenter/resources/hey050819.mspx
http://msdn.microsoft.com/en-us/library/ms974559
复制内容到剪贴板
代码:
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001

Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")

strPathToTextFile = "C:\Scripts\"
strFile = "Test.txt"

objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
      "Data Source=" & strPathtoTextFile & ";" & _
          "Extended Properties=""text;HDR=NO;FMT=Delimited"""

objRecordSet.Open "Select DISTINCT * FROM " & strFile, _
    objConnection, adOpenStatic, adLockOptimistic, adCmdText

Do Until objRecordSet.EOF
    Wscript.Echo objRecordSet.Fields.Item(0).Value   
    objRecordSet.MoveNext
Loop
速度还不错,但文本不能太复杂,因为有FMT=Delimited

或者通过Schema.ini文件指定按固定长度(但长度多少才算合适?)

作者: linuxfly   发布时间: 2010-11-06