Board logo

标题: [文本处理] 如何提高批处理删除重复内容文本的效率? [打印本页]

作者: playinthesky    时间: 2013-3-11 22:54     标题: 如何提高批处理删除重复内容文本的效率?

多个文本内有重复的字符,我设定一旦有重复的,就将其所含内容的整个文本删除,但是效率非常低下,1000个txt文档,就需要好几分钟。而我这里有上万个,求高手能否改进?
  1. @echo off&setlocal enabledelayedexpansion
  2. for %%a  in (*.txt) do (
  3.     for /f "usebackq delims=. tokens=2,*" %%b in (%%a) do (
  4.         set "str=%%b"
  5. set "str=!str: =!"
  6.         for %%i in (!str!) do (
  7. set/a _%%i+=1
  8.                 if !_%%i! gtr 2 echo %%a>>1.txt  2>nul  
  9.         )
  10.     set _%%i=
  11.     )
  12. )
  13. pause
复制代码
我这里写的是读入 1.txt

然后在读入的内容中发现

33303564545.txt
33303564545.txt
33303564545.txt
33303564545.txt
999999999999999.txt
999999999999999.txt
999999999999999.txt

以上是ECHO出来的,就是条件循环判断正确的,就其删除,但是会出现好几次,有上万个这样的文件,所以我想先写入一个文本,然后再根据文本上的地址删除,不知道有没有更加高效的方法,做到可以让删除的提示不出现那么多次,2>NUL 只是假象。。

意思就是换成 DEL 里面的路径文件,依旧效率不高,最好能只显示一次,然后一次性删除,不符合条件的文本。因为有上万个,希望能高效一点,求好心人解决!

运行是正常的,就是效率很低下。。
作者: playinthesky    时间: 2013-3-11 23:13

通过在BATHOME的学习,慢慢的学会写代码,希望大家再帮帮我,自己顶一下。
作者: playinthesky    时间: 2013-3-11 23:16

因为批处理每个都要历遍,但是为什么删除的时候,循环要检查好几次?
作者: wankoilz    时间: 2013-3-11 23:30

这种情况,上万个文件用纯批来处理估计有点慢哦
作者: terse    时间: 2013-3-11 23:32

这样提高点不
  1. @echo off&setlocal enabledelayedexpansion
  2. (for %%i in (*.txt) do (
  3.     set "a="
  4.     for /f "delims=" %%j in ('sort "%%i"') do (
  5.         if not defined a (
  6.            if "!str!" == "%%j" set a=a&echo del "%%i"
  7.            set "str=%%j"
  8.         )
  9.     )
  10. ))>$.#
  11. start "" "notepad" "$.#"
  12. pause
复制代码

作者: playinthesky    时间: 2013-3-11 23:35

回复 5# terse


    我那个是有格式的,所以必须按照上面的那种分隔符来,我去试试看!最最主要上万个。。
作者: playinthesky    时间: 2013-3-11 23:36

回复 5# terse


    是加在最后?对么?试试看!
作者: terse    时间: 2013-3-11 23:47

回复  terse


    我那个是有格式的,所以必须按照上面的那种分隔符来,我去试试看!最最主要上万个。 ...
playinthesky 发表于 2013-3-11 23:35

有固定格式的话 把第二FOR 替换这样试
  1. for /f "tokens=2 delims=." %%j ..........
复制代码

作者: playinthesky    时间: 2013-3-11 23:56

回复 8# terse


    超级高!!!非常快!!!谢谢高手,那我就是要那个文本文件改写成.BAT就可以吧?可不可以直接一点的。。
作者: CrLf    时间: 2013-3-11 23:59

纯批的话我会这样:
  1. @echo off
  2. findstr . *.txt|sort /o tmp.$
  3. (for /f "tokens=1* delims=:" %%a ni (tmp.$) do (
  4.    set "str=%%a"
  5.    setlocal enabledelayedexpansion
  6.    if !last!==!str! del "%%a"
  7.    endlocal
  8.    set last=%%a
  9. )) 2>nul
  10. pause
复制代码

作者: playinthesky    时间: 2013-3-11 23:59

本帖最后由 playinthesky 于 2013-3-12 00:07 编辑

回复 8# terse


    我想加入计数器,在第二个FOR里面,重复内容5个以上的时候,删除文本,你的这个版本真心好!
作者: playinthesky    时间: 2013-3-12 00:01

回复 10# CrLf


    是纯批处理,可不可以加入一个计数器,等到重复到一定个数的时候删除?求教。
作者: playinthesky    时间: 2013-3-12 00:03

回复 5# terse


    高手,加个计数器,等到重复两个或者三个的时候,直接删除。谢谢
作者: playinthesky    时间: 2013-3-12 00:05

回复 5# terse


    重复的数量上有限定要求,加入计数器在哪里比较好?
作者: CrLf    时间: 2013-3-12 00:19

本帖最后由 CrLf 于 2013-3-12 00:39 编辑

文件又多又大的话,用 vbs 会快很多
  1. Const [路径]="."       '这里设置路径
  2. Const [重复次数]="1"   '代表重复达到多少次就删除
  3. Set fso = CreateObject("scripting.filesystemobject")
  4. For Each file In fso.GetFolder([路径]).Files
  5. If LCase(fso.GetExtensionName(file)) = "txt" Then
  6. If reTest(fso.OpenTextFile(file).ReadAll) Then
  7. file.Delete
  8. End If
  9. End If
  10. Next
  11. Function reTest(text)
  12. Set re = New RegExp
  13. re.Global = True
  14. re.Pattern = "\n(\S+)(?:(?:\n.*)?\n\1){" & [重复次数] & ",}\n"
  15. reTest = re.Test(vbCrLf & text & vbCrLf)
  16. End Function
复制代码

作者: playinthesky    时间: 2013-3-12 00:26

回复 15# CrLf


    大哥,我的意思是在我最初写的代码里,GTR 3 或者 4 或者 5 可以吗?或者 LSS 也成,加个计数器,谢谢你!!你们的代码都很高深,我不知道如何插入?谢谢了。。我要计算重复大于5个的文件删除之类,可以实现吗?
作者: playinthesky    时间: 2013-3-12 00:29

回复 15# CrLf


    问题是有固定格式的。。对不起,已经很烦扰你了。。我需要 用 . 作为分割,然后把空格消掉,所以才在顶楼这样写。。。谢谢。。
作者: CrLf    时间: 2013-3-12 00:40

回复 17# playinthesky


    我都用中文变量名了还看不出来怎么设置重复次数吗...
作者: playinthesky    时间: 2013-3-12 01:01

本帖最后由 playinthesky 于 2013-3-12 06:08 编辑

回复 18# CrLf


    重复次数,我理解的,我的意思是它那个文件上有格式方面的限制,比方说ABCDABCD,如果说重复的话,A不是出现了两次,但是我是一个数组,所有是ABC为一个组合出现,需要计数,所以用了TOKENS和DELIMS,
作者: playinthesky    时间: 2013-3-12 01:05

本帖最后由 playinthesky 于 2013-3-12 06:07 编辑

回复 10# CrLf
作者: wankoilz    时间: 2013-3-12 09:21

本帖最后由 wankoilz 于 2013-3-12 09:23 编辑

15楼pattern中 (?:\n.*) 我不太明白,按我的理解我觉得应该加上一个回车符   (?:\r\n.*)
还望解答!
作者: Herculeslove    时间: 2013-3-12 19:21

回复 5# terse


    能否历遍子目录 ? 我用dir /a-d/b/s *.txt  一直出错。
作者: BAT-VBS    时间: 2013-3-12 21:08

回复 22# Herculeslove
  1. @echo off&setlocal enabledelayedexpansion
  2. (for /f "delims=" %%i in ('dir /a-d/b/s *.txt') do (
  3.     set "a="
  4.     for /f "delims=" %%j in ('sort "%%i"') do (
  5.         if not defined a (
  6.             if "!str!" == "%%j" (
  7.                 set a=a
  8.                 echo del "%%i"
  9.             )
  10.             set "str=%%j"
  11.         )
  12.     )
  13. ))>$.#
  14. start "" "notepad" "$.#"
复制代码

作者: CrLf    时间: 2013-3-12 21:52

回复 21# wankoilz


    .* 不跨行是针对 \n 的,\r 会被包含在 .* 或 \S+ 中,所以对结果没有影响,但若要严谨确实应该加上 \r
作者: wankoilz    时间: 2013-3-12 23:16

回复 24# CrLf
\S  与任何非空白的字符匹配。等价于"[^ \f\n\r\t\v]"。

按照帮助文档的说法,\S应该不包含\r才对啊
作者: CrLf    时间: 2013-3-12 23:38

回复 25# wankoilz


    噢,那也许 regexp 里的 \n 实际上匹配的是 \r?\n 吧?
作者: wankoilz    时间: 2013-3-13 00:04

我还是觉得该加一个\r




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