标题: [文本处理] [已解决]批处理如何将文件指定字符后面的所有段落合并为一段? [打印本页]
作者: plues 时间: 2010-9-30 11:52 标题: [已解决]批处理如何将文件指定字符后面的所有段落合并为一段?
请教各位老师,
有N个txt文件。每个文件至少包含一个特定的字符。
问题:如何将这个指定字符后面的所有段落内容合并为一段,指定字符前面的文本内容不做处理。
示例某一txt文件内容(“详细说明”为指定字符):
--------------------------------------------------
详细说明:
在正常情况下,无线路由器和访问点都拥有防止未知的无线设备连接到网络的能力。
这种功能是通过比较试图连接到路由器的设备MAC地址和路由器所保存设备的MAC地址而实现的。
不过,不幸的是,在路由器出厂时这种特性通常是关闭的,因为这需要用户的一些努力才能使其正确工作,否则反而无法连接网络。因此,通过启用这种特性,并且只告诉路由器本单位或家庭中无线设备的MAC地址,我们就可以防止他人盗用自己的互联网连接,从而提升安全性。(文本末)
--------------------------------------------------
批处理的结果:
--------------------------------------------------
详细说明:在正常情况下,无线路由器和访问点都拥有防止未知的无线设备连接到网络的能力。 这种功能是通过比较试图连接到路由器的设备MAC地址和路由器所保存设备的MAC地址而实现的。 不过,不幸的是,在路由器出厂时这种特性通常是关闭的,因为这需要用户的一些努力才能使其正确工作,否则反而无法连接网络。因此,通过启用这种特性,并且只告诉路由器本单位或家庭中无线设备的MAC地址,我们就可以防止他人盗用自己的互联网连接,从而提升安全性。(文本末)
--------------------------------------------------
盼请高手拨刀相助,谢谢!
[ 本帖最后由 plues 于 2010-10-1 15:07 编辑 ]
作者: bat_521 时间: 2010-9-30 12:24 标题: 表达不准确
你的每个txt文本里面 都以 "详细说明"字符 后面的内容为目标?
作者: plues 时间: 2010-9-30 13:07
是的。如果偶尔有个txt文件不包含“详细说明”,那么跳过此文件即可,不用处理。
作者: yangfengoo 时间: 2010-9-30 13:23
详细说明 后面的字数如果过多久不好处理了
作者: plues 时间: 2010-9-30 14:04
确实存在这个问题。“详细说明”后面的字数各个txt均不同。最少的有几十个字符,最多的一个有15000字。
如果批处理无法处理太多的字符,就判断txt文件的大小(1K字节以内的占绝大多数,1~10k字节的较少),如果大于多少k就跳过处理,只处理字数较少的就行了,字数多的手动修改。
作者: CUer 时间: 2010-9-30 14:40
- sed -i "/^详细说明/,${:a; $!N; s/\n//; ta; P; D}" 1.txt
复制代码
作者: yangfengoo 时间: 2010-9-30 14:47
- @echo off&setlocal enabledelayedexpansion
- for %%i in (*.txt) do (
- for /f "delims=:" %%a in ('findstr /n "详细说明:" "%%~i"') do set n=%%a&set nn=
- for /f "tokens=1* delims=:" %%a in ('type "%%~i" ^| findstr /n .*^&del /s/q "%%~i"') do (
- if %%a leq !n! (echo,%%b>>"%%~i") else (set nn=!nn!%%b)
- )
- echo,!nn!>>"%%~i"
- )
- set /p=处理完毕
复制代码
作者: plues 时间: 2010-9-30 14:52
感谢CUer老师热情相助!
以下是执行错误信息,烦请再修正一下错误:
环境变量 -i "/^详细说明/,${:a; $!N; s/\n//; ta; P; D}" 没有定义
作者: CUer 时间: 2010-9-30 14:59
你有sed.exe吗?哪个版本?
作者: asnahu 时间: 2010-9-30 15:18
先发个样本来看看。你的解释有点乱。
作者: plues 时间: 2010-9-30 16:30
原意是有N个txt文件需要处理,而且只处理位于txt中关键字是“详细说明”后面的段落(至文件尾),“详细说明”前面的所有文本内容均不处理,保持原状。
可能是我问题叙述的不太清晰。发个示例文件及处理后的文件,供各位老师参考。
CUer老师的sed只能执行1个文件,输出结果是txt中所有段落都合并了。
yangfengoo老师的代码思路是对的。不足之处就是文本末的最后面多出了一行,打印出了文件的路径,可否去掉这个路径。另外,可否在“详细说明”后面直接跟着下面的段落内容?
谢谢几位老师的大力帮助!
[ 本帖最后由 plues 于 2010-9-30 16:54 编辑 ]
作者: CUer 时间: 2010-9-30 17:23
- sed -i "/^详细说明/,${:a; $!N; s/\n//; ta; P; D}" *.txt
复制代码
作者: CUer 时间: 2010-9-30 17:24
输出结果是txt中所有段落都合并了?你用的哪个版本的sed啊?
作者: plues 时间: 2010-9-30 17:55
回CUer老师,sed 版本 4.1.5
输出不但所有段落都合并了,而且原文本的每行的在输出后就加了一个小小的黑色方块■
作者: yangfengoo 时间: 2010-9-30 20:53
把 leq 改成 lss 就是了- @echo off&setlocal enabledelayedexpansion
- for %%i in (*.txt) do (
- for /f "delims=:" %%a in ('findstr /n "详细说明:" "%%~i"') do set n=%%a&set nn=
- for /f "tokens=1* delims=:" %%a in ('type "%%~i" ^| findstr /n .*^&del /s/q "%%~i"') do (
- if %%a leq !n! (echo,%%b>>"%%~i") else (set nn=!nn!%%b)
- )
- echo,!nn!>>"%%~i"
- )
- set /p=处理完毕
复制代码
怎么会多一行? 本地测试没问题
作者: plues 时间: 2010-9-30 21:51 标题: 回复 15楼 的帖子
太棒了!
只剩下一处美中不足的地方,就是输出的txt文件末尾自动添加了“\路径\txt文件名.txt”的内容,可否将这处自动添加的内容去掉?
示例原文件保存于根目录下的“新建文件夹中”,则输出结果如下:
--------------------------------------------------
发表时间:2010年
作者:批处理
点击数:1
详细说明: 在正常情况下,无线路由器和访问点都拥有防止未知的无线设备连接到网络的能力。 这种功能是通过比较试图连接到路由器的设备MAC地址和路由器所保存设备的MAC地址而实现的。 不过,不幸的是,在路由器出厂时这种特性通常是关闭的,因为这需要用户的一些努力才能使其正确工作,否则反而无法连接网络。因此,通过启用这种特性,并且只告诉路由器本单位或家庭中无线设备的MAC地址,我们就可以防止他人盗用自己的互联网连接,从而提升安全性。(文本末)\新建文件夹\原文件.txt
--------------------------------------------------
再次感谢yangfengoo老师!
作者: asnahu 时间: 2010-10-1 00:33
- gawk -f comb-lst.awk urfile.txt > new.txt && type new.txt
复制代码
- {
- if($0 ~ /详细说明/){
- linenum = nr
- printf("%s",$0)
- }
- else if(linenum){
- printf("%s",$0)
- }
- else if(!linenum){
- print $0
- }
- }
复制代码
试试看能不能用。gawk为第三方软件,本论坛有下载。
[ 本帖最后由 asnahu 于 2010-10-1 13:32 编辑 ]
作者: CUer 时间: 2010-10-1 01:29 标题: 回复 14楼 的帖子
-i会直接修改原文件,哪里来的输出?
作者: terse 时间: 2010-10-1 03:57
- @echo off
- for /f "tokens=1,2 delims=:" %%i in ('findstr /lin "详细说明:" "*.txt"') do (
- >~emp set/p=详细说明:<nul
- (for /f "tokens=*" %%a in ('more +%%j "%%i"') do set/p=%%a<nul)>>~emp
- move ~emp "%%i"
- )
- pause
复制代码
作者: plues 时间: 2010-10-1 08:48 标题: 回复 17楼 asnahu 的帖子
测试结果是,代码执行后没有对原文本文件进行处理。不知问题出在哪儿。
也用了CUer的sed命令,结果都不理想。
[ 本帖最后由 plues 于 2010-10-1 08:52 编辑 ]
作者: plues 时间: 2010-10-1 08:49 标题: 回复 19楼 terse 的帖子
terse老师的代码执行后,实现了“详细说明”后面所有段落的合并,但将“详细说明”前面的文本内容全部删除了。
原题:如何将这个指定字符后面的所有段落内容合并为一段,指定字符前面的文本内容不做处理。
代码很好地实现了段落合并的需要,但忽视了后面“指定字符前面的文本内容不做处理”的要求。
请terse老师再修改一下。可参考15楼yangfengoo老师的代码。
yangfengoo老师的代码,唯一不足之处就是代码执行后在原文本末自动添加了\路径名\txt文件名.txt的内容。如果能去掉这些自动添加的内容就完美了。
谢谢各位老师热心跟帖解答。
[ 本帖最后由 plues 于 2010-10-1 08:53 编辑 ]
作者: asnahu 时间: 2010-10-1 09:13 标题: 回复 20楼 的帖子
代码生成new.txt文件,源文件没修改。另外,如果gawk、sed都不能正确执行,请说明你的系统环境。
作者: CUer 时间: 2010-10-1 10:36 标题: 回复 20楼 的帖子
我用的sed 4.1.4
拿你11楼的数据做测试,得到的结果给你提供的结果一样,不知道哪里不理想。
作者: powerbat 时间: 2010-10-1 11:28
来个js- folder = "C:\\test2"; //目录路径请用\\
- overWrite = 0; //是否替换原文件
-
- fso = new ActiveXObject("Scripting.FileSystemObject");
- if (!overWrite) {
- if (!fso.FolderExists(folder+'\\new'))
- folder2 = fso.CreateFolder(folder+'\\new').Path;
- else
- folder2 = folder+'\\new';
- } else {
- folder2 = folder;
- }
- e = new Enumerator(fso.GetFolder(folder).Files);
- for (; !e.atEnd(); e.moveNext())
- {
- f = e.item();
- if (f.Name.slice(-3).toLowerCase()=='txt') deal( f.Name );
- }
-
- function deal(file)
- {
- var s='';
- s = fso.OpenTextFile(folder+'\\'+file).ReadAll();
- s=s.replace(/详细说明[\s\S]*/gm, function(ss){return ss.replace(/[\r\n]/g,'');});
- fso.OpenTextFile(folder2+'\\'+file,2,true).Write(s);
- //return(s);
- }
复制代码
作者: plues 时间: 2010-10-1 13:24 标题: 回复 23楼 CUer 的帖子
奇怪,我换了不同的系统(winxp,win2003),不同版本的Sed(4.1.14 ,4.1.5),不同的电脑,结果都是一样。
作者: asnahu 时间: 2010-10-1 13:44
文本的断行有问题,可以试试GNU SED 4.2。文本是网页转过来的吧。
作者: plues 时间: 2010-10-1 15:05
天哪,竟然成功了!
按照asnahu的提示换了sed 4.2的版本,问题圆满解决!
在此,一并致谢yangfengoo、CUer、asnahu、terse、powerbat老师的大力相助!辛苦了!
同一问题,各位老师各施武艺,用不同的思路出发,使用了批处理、sed、gawk、JS,可谓殊途同归,不得不赞叹批处理之家高手云集,向您们深深的致谢!
作者: terse 时间: 2010-10-1 18:14
原帖由 plues 于 2010-10-1 08:49 发表
terse老师的代码执行后,实现了“详细说明”后面所有段落的合并,但将“详细说明”前面的文本内容全部删除了。
原题:如何将这个指定字符后面的所有段落内容合并为一段,指定字符前面的文本内容不做处理。
代码 ...
- @echo off&setlocal enabledelayedexpansion
- for %%a in (*.txt) do (
- set "i="
- (for /f "usebackq delims=" %%i in ("%%~a") do (
- set str=%%i
- if "!str:详细说明:=!" neq "%%i" set i=i
- if defined i (set/p=%%i<nul) else echo %%i
- ))> ~emp
- move ~emp "%%a"
- )
- pause
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |