![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-10 14:08 |
共 47,811 主题排行 / 349,897 发帖 / 今日 0 篇 / 48,255 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » 如何用批处理按标记分割文件 |
| 可打印版本 13,436 / 30 |
| 第1楼 yhsean | 发表于 2005-12-05 13:02 |
| 初级用户 发帖 26 积分 90 | |
|
如何用批处理按标记分割文件 现 有一文件 AA.TXT
内容如下: FGAFFFFSFF GGFDGG R*01 FSFF HHH R*02 FSDGF HDFH GHGH JJHGJR R*03 .... kljljfljfkj fmlfk R*n 请问如何将文件按照R*标记分割,名字按*后字符为名字 即:01.txt 内容为 01.txt FGAFFFFSFF GGFDGG 02.txt 内容为 02.txt FSFF HHH 03.txt 内容为 03.txt FSDGF HDFH GHGH JJHGJR ..... n.txt内容为 n.txt kljljfljfkj fmlfk 实际情况可能被分割的文件AA.TXT很大,分割的效率是务必考虑的 在此先感谢各位前辈们 [ Last edited by yhsean on 2005-12-8 at 13:33 ] |
|
| 第2楼 willsort | 发表于 2005-12-05 14:29 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re yhsean:
使用批处理分割文件的效率不太可能很高,如果在其中使用第三方工具,则就脱离了批处理的意义。下面给出 cmd 下的例句,直接在命令行使用,使用了最简的原型,一些含有特殊符号的行可能不会正确的输出,比如含有*的非文件标记行。 for /f "tokens=1,2 delims=*" %f in (aa.txt) do @if "%f"=="R" (ren temp %g.txt) else (echo %f>>temp) |
|
| 第3楼 yhsean | 发表于 2005-12-05 18:39 |
| 初级用户 发帖 26 积分 90 | |
|
感谢版主回复
我也是用上面命令完成分割,但是当文件太大的时候,执行效率非常低,这样在实际工作中用的话,意义就不十分大了 刚来改论坛,感觉版主非常热心,再一次致谢。 贴出的目的在于能否找到一种更简洁有效的办法,不知道用DEBUG有没办法实现 |
|
| 第4楼 yhsean | 发表于 2005-12-05 18:55 |
| 初级用户 发帖 26 积分 90 | |
|
另外请问版主如果使用第三方工具,如何在批处理中调用工具,(调用过程中,工具实现功能的时候强调完全自动——不能人工参与)
文件除了标记*外无别的* |
|
| 第5楼 willsort | 发表于 2005-12-05 19:02 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re yhsean:
DEBUG 应该可以实现,只是会更复杂,效率会更低,而且 debug 本身对大文件的处理性能也不是很理想。 批处理调用的第三方工具需要有一定的选择性,我们首选可以在命令行参数中进行全部操作的工具,其次才会考虑需要在运行过程中动态交互的工具,此时需要精心设计一个完备的应答文件。 你的问题应该可以用 sed 简单的实现,只是现在没有时间了;明天中午之前,若无其它达人提供此方案的实现,我会考虑完成一个。 |
|
| 第6楼 yhsean | 发表于 2005-12-06 08:54 |
| 初级用户 发帖 26 积分 90 | |
|
昨天晚上下了个 SSED FOR WIN32 ,网上一番研究用法,介于行道太浅,未找出解决方案。因工作十分需要,期待willsort师之答案,感激不尽
另外众多SED版本中,是否SSED 会更好些 |
|
| 第7楼 无奈何 | 发表于 2005-12-06 11:29 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
to yhsean
SED 是基于行的流编辑器不适合文本的分割。可以用 csplit 来完成这个分割任务。 下面给你提供一个方案,如下: 1、先执行下面的语句,分割文本。 2、生成文件重命名对照文件。 3、删除文件最后一行,并重命名文件。 说明: 1、以上提到的第三方工具可以从 GNU utilities for Win32 工具包中找到。 2、SED 过低版本不支持 -i 参数,请使用 GNU SED ,非 GNU SED 与其表达式有部分差异,我不能保证能得到正确结果。 3、你可以将上面语句存为批处理文件执行。 如有问题跟贴提出。 |
|
| 第8楼 yhsean | 发表于 2005-12-06 23:38 |
| 初级用户 发帖 26 积分 90 | |
|
谢谢解答,想必无奈何先生是专业程序员,我只是应用者,为完成方案,研究SED好长时间,找不到解,毕竟对于一个应用者来说,学习大量的工具是有难度的,介于SED命令的广泛性(自我感觉而已),所以肯请那位仁兄给出SED之解。
实际应用的时候为一应用软件动态产生该脚本,所以代码的简洁性有助于方便定制应用软件使其生成脚本。再次感谢无奈何先生 |
|
| 第9楼 yhsean | 发表于 2005-12-07 13:17 |
| 初级用户 发帖 26 积分 90 | |
|
终于找到方案了
请willsort师帮忙检查下代码能否在简洁一点 算法是否合理 因为 * 在SED有特殊意义,所以将 * 改为了 | ::net send * *** echo off set file=AA.txt set/a m=1 set/a n=1 set/a L=0 for /f %%a in ('SED -n "/R|/p" ./%file%') do (set/a L+=1) if %L%==1 (copy %file% %m%.ok&goto end) SED "1,/R|/!d" ./%file% >%m%.ok SED "1,/R|/d" ./%file% >%n%.tmp :loop set/a m+=1 set/a p=-1*%n% set/a L=0 for /f %%a in ('SED -n "/R|/p" ./%n%.tmp') do (set/a L+=1) if %L%==1 (ren %n%.tmp %m%.ok&goto end) SED "1,/R|/!d" ./%n%.tmp >%m%.ok SED "1,/R|/d" ./%n%.tmp >%p%.tmp set/a n*=-1 goto loop :end DEL *.TMP for %%a in (*.ok) do ( for /f "tokens=2 delims=|" %%b in ('SED -n "/R|/p" %%a') do (ren %%a %%b) ) ::net send * *** net send只是利用消息时间差测试处理时间 [ Last edited by yhsean on 2005-12-7 at 14:25 ] |
|
| 第10楼 willsort | 发表于 2005-12-07 20:27 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re 无奈何:
csplit 确实是个不错的文本模式分割工具,使用起来要比 sed 简单许多。但是从效率上来考虑,我认为他们相差不会很大,因为二者的核心都是对文本进行以行为单位的模式匹配。而从你的方案来看,除了第一步中对全文进行了扫描之外,查找文件名的findstr语句和删除最后一行的sed语句实际上也相当于扫描全文,三次全文扫描显然会降低效率。 而理论上这个项目应该是可以通过一次扫描实现的,比如我最先提到的for /f方案,当然我目前尚未完成一次扫描的 sed 方案,主要困难在于如何给文件命名上。现在想来,通过 sed 来完成确实不是太好的方案。就目前得知,awk应该可以完成,只是对它仍很陌生。 Re yhsean: 你的代码我没有仔细研究,但理解了你的大致思路,是分割出一个文件命名一个文件,然后再继续分割,这样实际上对文本扫描的次数更多了,效率应该更难保证。 你提到了更改了匹配模式,那么是否意味着 aa.txt 的格式你是可以自由定制的?甚或你对 aa.txt 有着更多的操作自由度?若果然如此,我们可以继续改善这个模式,以更利于工具的匹配。 |
|
| 第11楼 tigerpower | 发表于 2005-12-07 23:44 |
| 中级用户 发帖 99 积分 377 | |
|
既然板主对awk很陌生,何以断定它可以完成任务呢
![]() |
|
| 第12楼 yhsean | 发表于 2005-12-08 13:01 |
| 初级用户 发帖 26 积分 90 | |
|
感谢版主,aa.txt是由一应用软件产生,其中最后行内容可以自己定制
另外被分割的文件有不确定的若干部分(由软件动态产生) 还有个问题就是实际中还要将分割后最后一行搬移到每一个分割后文件前面指定行(比如2行后) 真诚希望得到版主的帮助,SED也是猛肯了两天,别的工具是一点不懂啊 (不过尽管如此,SED多次扫描文件全文,但比起那个FOR /F也快十几倍) [ Last edited by yhsean on 2005-12-8 at 13:11 ] |
|
| 第13楼 无奈何 | 发表于 2005-12-08 13:16 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
to tigerpower
这是个眼界问题,我猜想 willsort 兄所说的陌生只是相对AWK语法来说的,而并非一无所知。 to yhsean 我只是一名命令行爱好者。对于工具的学习与使用,我个人认为多接触一些是有好处的,某些任务用某一种工具很难完成,但换用其他工具可能很容易,更重要的是拓宽了思路顺便掌握了更多的知识与技巧。 ===== 一直以来很畏惧 AWK ,几次尝试学习都退缩回来,至今未能入门。这次带着本帖的问题匆匆浏览了一些文章,发觉这东西真的很有意思,也并非如我原先想像中的难以掌握。因为是有针对性的阅读,所以最后学到的东西不多不少刚刚能够完成这个任务,也不知道语句是否合理,毕竟对 AWK 的了解太少了。 在命令行下执行 gawk -f AA.awk AA.txt AA.awk 如下: |
|
| 第14楼 yhsean | 发表于 2005-12-08 21:37 |
| 初级用户 发帖 26 积分 90 | |
|
请 无奈何 或斑竹告诉如何用SED将文件的末行移动到前面指定行
经过改进代码如下: @echo off set file=aa.txt set/a n=1 set/a L=0 :loop sed -n "1,/R|/p" .\%file%|sed -n "$p" >tmp.tmp for /f "tokens=3 delims=| " %%a in (tmp.tmp) do (set Tim=%%a) for /f "tokens=3 delims=| " %%a in (tmp.tmp) do (set Nam=%%a.fanuc1) sed -n "1,/R|/p" .\%file% >%Nam% ::判断已经处理的文件是否只有一部分(或是否为最后一部分) for /f %%a in ('sed -n "/R|/p" .\%file%') do (set/a L+=1) if %L%==1 goto end set/a L=0 ::取出第一部分后的部分;输出临时文件 sed -n "1,/R|/!p" .\%file% >%n%.tmp ::改变被处理的文件 set file=%n%.tmp ::反转临时文件以提供下次输出 set/a n*=-1 goto loop :end del *.tmp [ Last edited by yhsean on 2005-12-8 at 21:40 ] |
|
| 第15楼 无奈何 | 发表于 2005-12-09 00:36 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
to yhsean
你应该掌握一些正则表达式的知识,关于特殊字符 * 可以这样 \* 脱掉其特殊性。 你提到的将文件的末行移动到前面指定行前,可以这样实现。 假定移至第三行前。 还是那个问题,如果你追求执行效率可以用下面的命令。 |
|
| 1 2 3 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |