中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » 用批处理也可以简单实现删除文本相同行
« [1] [2] »
作者:
标题: 用批处理也可以简单实现删除文本相同行 上一主题 | 下一主题
youxi01
高级用户




积分 846
发帖 247
注册 2006-10-27
来自 湖南==》广东
状态 离线
『楼 主』:  用批处理也可以简单实现删除文本相同行

@echo off
echo 正在查找文本相同行,请等待.....
(echo 清除重复行后的文件内容:& echo.)>str_.txt

setlocal enabledelayedexpansion
for /f "delims=" %%i in (test.txt) do (
    if not defined %%i set %%i=A & echo %%i>>str_.txt)

echo 清理完毕,清理后的文件保存在:str_.txt
pause>nul

经过测试,基本达到删除相同行的目的,但是暂时没有处理空行。

2006-10-31 21:53
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 2 楼』:  

  用文本行的内容是否已经被定义过来决定是否输出,实现了代码的简洁化,比起常规思路要节省N多代码,楼主的手段确实高明。

  观察你的代码,并没有用到变量延迟,所以 setlocal enabledelayedexpansion 一句可以省略。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2006-10-31 22:25
查看资料  发短消息 网志   编辑帖子  回复  引用回复
9527
银牌会员

努力做坏人


积分 1185
发帖 438
注册 2006-8-28
来自 北京
状态 离线
『第 3 楼』:  

不过对与以下形式的文本好像就无能为力了

A HELLO WORLD
set c=
A YOU
HELLO YOU
set a=
A YOU
set sdfs=
set sdfs=
HEllo you
set c=
you are very good



我今后在论坛的目标就是做个超级坏人!!!
2006-10-31 23:17
查看资料  发短消息 网志  OICQ (329429)  编辑帖子  回复  引用回复
NaturalJ0
银牌会员




积分 1181
发帖 533
注册 2006-8-14
状态 离线
『第 4 楼』:  

如果有一万行似乎也行不通。

2006-10-31 23:19
查看资料  发短消息 网志   编辑帖子  回复  引用回复
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 5 楼』:  

  看来对不符合变量命名规则的行内容、超过变量个数限制的文本都无法正确处理。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2006-10-31 23:27
查看资料  发短消息 网志   编辑帖子  回复  引用回复
youxi01
高级用户




积分 846
发帖 247
注册 2006-10-27
来自 湖南==》广东
状态 离线
『第 6 楼』:  

至于大小写的问题,倒是比较好处理:添一个开关 /I即可。
if /I not defined %%i set %%i=A & echo %%i>>str_.txt)
但是对于“特殊的文本行”还是没想到好的解决办法,望高手指点。

2006-11-1 00:58
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
lxmxn
版主




积分 11386
发帖 4938
注册 2006-7-23
状态 离线
『第 7 楼』:  


  小弟愚笨,不明白这一句(if /I not defined %%i set %%i=A & echo %%i>>str_.txt)为什么可以起到"删除文本相同的行"的作用,想了半天没想出来,还请各位大侠不吝赐教,详细的分析一下其机理。


2006-11-1 01:30
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 8 楼』:  

原理是每从test.txt里取一行就给它赋值为A,
例:如果取了一行“ABC”,那么它就让 ABC=A,这样是不是变量ABC非空值而是被定义了?

然后if not defined会依次检查从这个test.txt文本内取出来的每一行,
它把取出来的这一条当做一个变量来看,判断它是不是没被定义过,即看是否没有被赋值。

如果没有被赋值当然说明这个变量(取出来的这一行)跟本就出现过(没重复过),说明这行是非重复的行。

……
一直到结束,只要取一行就把这行以变量命名来赋个值,
只要将来判断新取的行(早被当做变量了)被赋过值,那一定是重复的,
所以就不往过滤后的文本文件内写东东了:)



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-11-1 01:52
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
youxi01
高级用户




积分 846
发帖 247
注册 2006-10-27
来自 湖南==》广东
状态 离线
『第 9 楼』:  

@echo off
echo 正在查找文本相同行,请等待.....
(echo 清除重复行后的文件内容:& echo.)>str_.txt
setlocal enabledelayedexpansion
for /f "delims=" %%i in (test.txt) do (
    set /a flag=0
    echo %%i | find "=" >nul && set /a flag=1
    for /f "tokens=1* delims==" %%a in ("%%i") do (
           if /i not defined %%a%%b (
           set %%a%%b=A
           if  !flag! equ 1 (echo %%a=%%b>>str_.txt) else echo %%a>>str_.txt
     )   
  )
)
echo 清理完毕,清理后的文件保存在:str_.txt
pause>nul

说明:以上代码成功解决“=”的问题,包括set var=(不含空格) set var=(含空格)
但以上代码仍然不能解决文本内容出现> <等一系列问题。

2006-11-1 02:03
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 10 楼』:  

  9F的代码虽然能解决一个“=”的问题,但是仍然不能解决多个“=”号的情况,并且速度非常慢,处理3F的文本也需要好几秒,问题出在 echo %%i|find "=" 这一句上。看来还得多费点心思。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2006-11-1 02:37
查看资料  发短消息 网志   编辑帖子  回复  引用回复
electronixtar
铂金会员





积分 7493
发帖 2672
注册 2005-9-2
状态 离线
『第 11 楼』:  

看来批处理不适合复杂的文本处理,天生缺陷啊。找找第三方工具试试




C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>"
2006-11-1 03:38
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
vkill
金牌会员





积分 4103
发帖 1744
注册 2006-1-20
来自 甘肃.临泽
状态 离线
『第 12 楼』:  

用sed可以轻松实现~ 处理问题时最有效的才是最好的,我是这样认为,用第三方工具又何妨?

http://www.cn-dos.net/forum/view ... 1&highlight=sed


选择性地删除特定行:
--------
# 显示通篇文档,除了两个正则表达式之间的内容
sed '/Iowa/,/Montana/d'
# 删除文件中相邻的重复行(模拟“uniq”)
# 只保留重复行中的第一行,其他行删除
sed '$!N; /^\(.*\)\n\1$/!P; D'
# 删除文件中的重复行,不管有无相邻。注意hold space所能支持的缓存
# 大小,或者使用GNU sed。
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
# 删除除重复行外的所有行(模拟“uniq -d”)
sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'
# 删除文件中开头的10行
sed '1,10d'
# 删除文件中的最后一行
sed '$d'
# 删除文件中的最后两行
sed 'N;$!P;$!D;$d'
# 删除文件中的最后10行
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # 方法1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # 方法2
# 删除8的倍数行
gsed '0~8d'                           # 只对GNU sed有效
sed 'n;n;n;n;n;n;n;d;'                # 其他sed
# 删除匹配式样的行
sed '/pattern/d'                      # 删除含pattern的行。当然pattern
                                       # 可以换成任何有效的正则表达式
# 删除文件中的所有空行(与“grep '.' ”效果相同)
sed '/^$/d'                           # 方法1
sed '/./!d'                           # 方法2
# 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。
# (模拟“cat -s”)
sed '/./,/^$/!d'        #方法1,删除文件顶部的空行,允许尾部保留一空行
sed '/^$/N;/\n$/D'      #方法2,允许顶部保留一空行,尾部不留空行
# 只保留多个相邻空行的前两行。
sed '/^$/N;/\n$/N;//D'
# 删除文件顶部的所有空行
sed '/./,$!d'
# 删除文件尾部的所有空行
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # 对所有sed有效
sed -e :a -e '/^\n*$/N;/\n$/ba'        # 同上,但只对 gsed 3.02.*有效
# 删除每个段落的最后一行
sed -n '/^$/{p;h;};/./{x;/./p;}'

2006-11-1 05:09
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
electronixtar
铂金会员





积分 7493
发帖 2672
注册 2005-9-2
状态 离线
『第 13 楼』:  

看来得下载一个sed了,哇咔咔




C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>"
2006-11-1 05:34
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
lxmxn
版主




积分 11386
发帖 4938
注册 2006-7-23
状态 离线
『第 14 楼』:  


  谢谢 redtek 的指点,明白了。开始还以为如果%%i的值是空值的话,就表示没有定义呢,现在才理解了"defined"的真正含义是要用"set"定义之后才算是"defined",呵呵。


2006-11-1 09:27
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
3742668
荣誉版主





积分 2013
发帖 718
注册 2006-2-18
状态 离线
『第 15 楼』:  


@echo off
    set file2=b.txt
    set file1=a.txt 4>%file2%
    set tmpVar=
    for /f "delims=: tokens=1,*" %%i in ('findstr /n .* %file1%') do (
        set tmpVar=%%j
        if not defined tmpVar ( >>%file2% echo.
                              ) else (
                                      findstr /xc:"%%j" %file2% || (echo %%j)>>%file2%
                                     )
    )
楼主所用的方法我也曾经尝试过,不过由于局限太大的原因基本不使用。用批处理来处理文件的确比较麻烦,处理比较特殊的文件的时候提倡还是用vbs或第三方工具。
对于数据量不大的情况,适当地使用批处理还是比较方便的:
@echo off
setlocal enabledelayedexpansion
    set old=xxx.txt
    set new=yyy.txt
    for /f "delims=: tokens=1,*" %%i in ('findstr /n .* %new%') do set "%%i=%%j" && set num=%%i
    call :whatyouwant
goto :eof

rem 反向显示文件
:last2first
    for /l %%i in (%num%,-1,1) do if defined %%i (echo !%%i!) else echo.
goto :eof

rem 过滤空行
:filter
    findstr . %old%
goto :eof

rem 在指定行插入内容,下面的例子是在第3行后插入,内容为%youstr%
rem 如果是要重定向到文件中则应该在%3%后面加上重定向语句
:insert
    set "3=%3%&&echo %youstr%"
    for /l %%i in (1,1,%num%) do echo !%%i!
goto :eof

rem 删除指定行,下面是删除第三行的例子
:delline
    set 3=
    for /l %%i in (1,1,%num%) do echo !%%i!
goto :eof

rem 只显示单数行.要显示双数行,以及先显示单数行,再显示双数行可以用同样的方法
:printOdd
    for /l %%i in (1,2,%num%) do echo !%%i!
goto :eof
时间关系,以上代码均未测试.暂时写这么一点东西,以后再把12F实现的功能全部写出来.
顺便向和俺一样双休日不得休息的同志们致敬!

2006-11-5 01:51
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: