Board logo

标题: [文本处理] 【练习-049】批处理按要求对齐整理文本内容 [打印本页]

作者: batman    时间: 2009-8-10 17:05     标题: 【练习-049】批处理按要求对齐整理文本内容

&&有文本a.txt内容如下:
  1. 3、接下来,你试着回答我一个问题批处理中最常用最复杂也是最强大的命令是哪个命令?
  2.     相信经过以上两次的训练,你会脱口而出“for”。是的,for命令的确是批处理中最重要的命令,学好它的意义是不容置疑的。管理员就此命令特为大家精心撰写了for命令从入门到精通一贴,你所要做的就是前前后后将此贴通遍,将其搞懂弄明白,并结合大量的for命令练习,以熟练掌握for命令的各种应用。
  3.                     至此,我可以说你已经脱菜了。但是不是掌握了for命令就可以“天下无敌,无坚不摧了呢”?非也,接下来,你还要继续提升自己。
复制代码
  要求通过批处理将其按60个左右的字节(一个英文字符占1字节,一个汉字字符占2字节)一行进行重整理(如遇分段可以不足60),同时对于空行要按原样输出,并且在每段(出现空行才视为分段)的开头空出两个汉字空格以对齐,生成的文本如下:
  1.   
  2.   3、接下来,你试着回答我一个问题批处理中最常用最复杂也是最
  3. 强大的命令是哪个命令?
  4.   相信经过以上两次的训练,你会脱口而出“for”。是的,for命令的
  5. 确是批处理中最重要的命令,学好它的意义是不容置疑的。管理员就此
  6. 命令特为大家精心撰写了for命令从入门到精通一贴,你所要做的就是
  7. 前前后后将此贴通遍,将其搞懂弄明白,并结合大量的for命令练习,以
  8. 熟练掌握for命令的各种应用。
  9.   至此,我可以说你已经脱菜了。但是不是掌握了for命令就可以“
  10. 天下无敌,无坚不摧了呢”?非也,接下来,你还要继续提升自己。
复制代码
  本题满分15分,先不考虑特殊字符但请注意代码通用性,视情况加分。

[ 本帖最后由 batman 于 2009-8-18 21:02 编辑 ]
作者: 523066680    时间: 2009-8-10 17:59

60个左右的字节


左右哦~   是你说的哦

我等到了下午,没想到还是没人回帖。来捧场了

我不是认真的,是为了找回以前认识你时的味道。玩偏方~

  1. @echo off&setlocal enabledelayedexpansion
  2. mode con cols=62 lines=25
  3. for /f "tokens=*" %%a in (text.txt) do (
  4.    set now=%%a
  5.    if "!now:~0,3!"=="   " (set "now=!now: =!")
  6.    set "now=  !now!"
  7.    echo,!now!
  8.    echo,
  9. )
  10. pause
复制代码

[ 本帖最后由 523066680 于 2009-8-10 18:00 编辑 ]
作者: batman    时间: 2009-8-10 18:12

呵呵,这次偏方玩得有点不对哦,请注意“生成文本如下”几个字。
作者: 523066680    时间: 2009-8-10 18:28

命令框应该和鼠标结合的嘛~      输出后用鼠标复制。

额,要用生成的方法啊?淡定,淡定。。。。。。
作者: Lumiere    时间: 2009-8-10 23:21

  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "tokens=*" %%a in (a.txt) do call :loop %%a
  3. pause>nul&goto :eof
  4. :loop
  5. set "s=    %1"&set i=34
  6. :again
  7. call set n=%%s:~0,!i!%%&echo !n!>>b.txt&call set m=%%s:!n!=%%
  8. set x=!m:~30,1!&(if not "!x!"=="" (set i=30&set s=!m!&goto again) else echo !m!>>b.txt)
  9. echo.>>b.txt
  10. goto :eof
复制代码
不知道这样符不符合题意……
作者: zhouyongjun    时间: 2009-8-11 00:14

哎,始终是效率问题,特殊字符也麻烦
  1. @echo off&setlocal enabledelayedexpansion
  2. ::下面设置每行显示的字节数
  3. set/a num=60
  4. set/a s=num/2-1
  5. for /l %%i in (1,1,%num%) do set "sign=!sign!."
  6. for /f "delims=" %%a in ('findstr/n ".*" a.txt') do (
  7. set "str=%%a"&set "str=!str:*:=!"
  8. if defined str for /f "tokens=* delims= " %%b in ("!str!") do set "str=  %%b"
  9. if defined str (set/a n=%s%&call :check) else echo/
  10. )
  11. pause>nul&exit
  12. :check
  13. if not defined str goto :eof
  14. set/a n+=1,m=n+1
  15. set var=!str:~,%n%!
  16. echo/%var%|findstr "%sign%" >nul 2>nul&&(
  17. set str=!str:~%n%!&echo/%var%&set/a n=%s%&goto check)||(
  18. if "!var!" equ "!str:~,%m%!" (echo/%var%&goto :eof) else goto check
  19. )
复制代码

作者: batman    时间: 2009-8-11 00:21

呵呵,从5楼的代码编写的思路就可以看出有以下几点不足:
   1、for默认是忽略空行的,代码首先就没有考虑到空行的输出;
   2、代码也没有对分段点和英文字符及中文字符进行判断;
   3、代码没有对每段的行首原有的空格进行有效处理;
   4、最后一个goto :eof是多余的;
   5、代码书写不规范。
   最后,希望兄弟继续努力,你的批处理水平将会越来越高的。

[ 本帖最后由 batman 于 2009-8-11 00:29 编辑 ]
作者: zhouyongjun    时间: 2009-8-11 00:27     标题: 回复 7楼 的帖子

回复batman兄,你可能没有测试代码,你说得情况都判断了的,只是代码效率不高
这是算法的问题了
至于书写贴上来是不规范了,我在计算机上看还可以。对于代码的缩进我目前也只是看着大家的代码凭感觉,没这方面的知识。
作者: batman    时间: 2009-8-11 00:31

我7楼的贴子是说的5楼的,已修改。。。
作者: zhouyongjun    时间: 2009-8-11 00:33     标题: 回复 9楼 的帖子

呵呵,回过头一看,我估计是batman兄在编辑帖子时我刚好发了贴。所以楼数不对了。(*^__^*)
作者: batman    时间: 2009-8-11 00:42     标题: 回复 6楼 的帖子

赞扬的话就不说了,下面提出本人的建议:
1、for /f "delims=" %%a in ('findstr/n ".*" a.txt')是否改为for /f "tokens=1* delims=:" %%a in ('findstr/n ".*" a.txt'),
而后面直接set "str=%%b"更为好一点?
2、for /f "tokens=* delims= " %%b in ("!str!") 此处欠妥,因为在行首有英文空格、汉字空格和tab三种情况,兄
弟只考虑了一种情况是不够的,同时如在文本正文中也有这三种字符呢?
3、用echo|findstr判断效率不如if判断。
4、书写确实存在一定的问题,代码可读性要加强。

[ 本帖最后由 batman 于 2009-8-11 00:46 编辑 ]
作者: zhouyongjun    时间: 2009-8-11 08:55     标题: 回复 11楼 的帖子

多谢batman兄的指点
第一个问题确实那样要好点。第二个问题没考虑到那么多,看到你范文前面是全角空格就当成全角空格了,考虑你说的情况加入delims分隔符集就可以了,论坛会把TAB变空格,我6楼就不改了。
问题三是关键,也是核心算法的问题,echo|findstr 这种方式实属无奈之举,我实在没有想到其他方法了,除开用临时文件的方法我暂时没想到怎么用if去判断。
期待大家完善的代码。。。
作者: Lumiere    时间: 2009-8-11 09:16     标题: 回复 7楼 的帖子

不是说60字节左右,我就没对英文字符判断了,不过空行问题确实没有解决。至于行首的空格,我复制你的文本,在我机器上运行效果很好啊,最大的一个问题就是没有处理空行。还有我发觉复制的时候空行里都有一个空格,可是复制到文本中后那个空格就消失了,不知道怎么回事。
作者: batman    时间: 2009-8-11 09:26     标题: 回复 13楼 的帖子

可能是本人在顶楼给出的文本有问题,这里再传上一份文本(此文本内容里就有三种空格,行首的需要处理,但行内的是要求原样输出的)同时附上本人的代码(注请将第一个tab字符替换成tab再运行):
  1. @echo off&setlocal enabledelayedexpansion
  2. set "k1= "&set "k2= "&set "k3=tab"
  3. for /f "tokens=1* delims=:" %%a in ('findstr /n .* a.txt') do (
  4.      set "str=%%b"
  5.      if defined str (
  6.         call :lp
  7.         ) else (
  8.         echo.&echo.&set "fd=a"
  9.      )
  10. )
  11. pause>nul&goto :eof
  12. :lp
  13. for %%a in ("%k1%" "%k2%" "%k3%") do if "!str:~,1!" equ %%a set "str=!str:~1!"&goto lp
  14. if defined fd set "str=  !str!"&set "fd="&set /a n=4
  15. :loop
  16. set /p=!str:~,1!<nul&set /a n+=1
  17. if "!str:~,1!" gtr "Z" set /a n+=1
  18. if %n% geq 60 set /a n=0&echo.
  19. set "str=!str:~1!"
  20. if defined str goto loop
复制代码
[attach]1733[/attach]
作者: zhouyongjun    时间: 2009-8-11 09:56     标题: 回复 14楼 的帖子

逐字显示是我一开始就放弃的想法,没想到速度比我的快(经测试硬是比我的快了10多毫秒,长文本就更明显了)。看来echo|findstr的方法是太不好了。
作者: terse    时间: 2009-8-11 10:28

是不是以空行分段的啊
作者: batman    时间: 2009-8-11 10:32     标题: 回复 16楼 的帖子

正是,不然批是达不到这种智能程度。
作者: terse    时间: 2009-8-11 13:54

用的临时文件
  1. @echo off&setlocal enabledelayedexpansion
  2. set k1=tab&set k2= &set "k3= "
  3. if "%k1%"=="tab" echo 上面这里set k1=tab设置成TAB键&pause&exit
  4. (for /f "tokens=1* delims=:" %%a in ('findstr /n .* a.txt') do (
  5.    if "%%b"=="" (
  6.        set "bk=  "
  7.        if defined var (echo;&echo;)else echo;
  8.        for %%b in (~tem.txt) do set/a n=%%~zb+60
  9.     ) else (
  10.        for /f "tokens=* delims=%k1%%k2%%k3%" %%i in ("%%b") do (
  11.        if defined n (set var=!bk!%%i&set "bk=")else set n=60&set var=!k2!!k2!%%i
  12.    )
  13.        >"%temp%\tem~.tem" echo !var!
  14.        for %%b in ("%temp%\tem~.tem") do set/a m=%%~zb-2
  15.        for /l %%i in (0 1 !m!) do (
  16.        if "!var:~%%i,1!" neq "" (
  17.        for %%b in (~tem.txt) do if %%~zb lss !n! (set/p=!var:~%%i,1!<nul)else (
  18.            echo;&set/p=!var:~%%i,1!<nul
  19.            set/a n=%%~zb+62
  20. ))))))>~tem.txt
  21. del "%temp%\tem~.tem"
  22. pause
复制代码

作者: netbenton    时间: 2009-8-12 22:41

一个for内解决问题,
  1. @echo off&setlocal enabledelayedexpansion
  2. set "tab=        "
  3. for /f "tokens=1* delims=:" %%a in ('findstr /o .* a.txt') do (
  4.         if "%%b" equ "" (echo;) else (
  5.                 for /f "tokens=* delims= %tab% " %%c in ("%%b") do (set str=%%c)
  6.                         set/a a=8180,c=0&for /l %%a in (1,1,14) do (
  7.                             set/a "b=(a-c)/2+c"&for %%b in (!b!) do if "!str:~%%b,1!" equ "" (set/a a=b) else (set/a c=b)
  8.                         )&rem 此段字符长度计算用到 随风 的折半法
  9.                         set n=4
  10.                         set "ec=    "
  11.                         for /l %%a in (0,1,!a!) do (set "one=!str:~%%a,1!"
  12.                             set ec=!ec!!one!
  13.                             if "!one!" geq "z" (set /a n+=2) else (set /a n+=1)
  14.                             if !n! geq 60 echo;!ec!&set ec=&set n=0
  15.                         )
  16.                         echo;!ec!
  17.         )
  18. )
  19. pause
复制代码

[ 本帖最后由 netbenton 于 2009-8-12 22:58 编辑 ]
作者: 523066680    时间: 2009-8-13 18:41

帮楼上的顶起来~
作者: batman    时间: 2009-8-14 00:34     标题: 回复 20楼 的帖子

代码还是存在一点问题,如出下以下文本时,代码会出错:
  1.         古人日:读书有三到,眼到、口到、心到。而我们
  2. 学习批处理则讲究四多:多看、多问、多想、
  3. 多练。那么这四多又分别是什么意思呢?
  4.     所谓多看就是多看看学习资料如教程,多看看别人写好的代码。。。
复制代码
上面的三行处理后应该是一句,而经20楼的代码处理后就成了三句,当然在现实中一般不会有这样的文字书写形式出现。
作者: netbenton    时间: 2009-8-14 07:56

已经解决21楼说的问题
  1. @echo off&setlocal enabledelayedexpansion
  2. set "tab= "
  3. for /f "tokens=1* delims=:" %%a in ('findstr /o .* a.txt^&echo;') do (rem 加个echo;最后补一行空行
  4. if "%%b" neq "" (set "str=!str!%%b") else (if defined str (rem 遇到空行并且段落不为空才分析
  5.          for /f "tokens=* delims= %tab% " %%c in ("!str!") do (set str=%%c)
  6.    set/a a=8180,c=0&for /l %%a in (1,1,14) do (
  7.        set/a "b=(a-c)/2+c"&for %%b in (!b!) do if "!str:~%%b,1!" equ "" (set/a a=b) else (set/a c=b)
  8.    )&rem 此段字符长度计算用到 随风 的折半法
  9.    set n=4
  10.    set "ec=    "
  11.    for /l %%a in (0,1,!a!) do (set "one=!str:~%%a,1!"&rem 根所段落长度来逐字判断
  12.        set ec=!ec!!one!
  13.        if "!one!" geq "z" (set /a n+=2) else (set /a n+=1)
  14.        if !n! geq 60 echo;!ec!&set ec=&set n=0
  15.    )
  16.    if defined ec echo;!ec!&rem 根据最后一节是否为空,在段落间加入空行,
  17.    echo;&set str=
  18. ))
  19. )
  20. pause
复制代码

[ 本帖最后由 netbenton 于 2009-8-14 08:03 编辑 ]
作者: zqz0012005    时间: 2009-8-14 13:20

临到考虑特殊字符的时候了。
使用了临时文件,且鉴于tab制表符的特殊性,将其替换成了一个空格。
  1. @echo off
  2. if "%~1" neq "" goto LTrimInit
  3. for /f "eol= tokens=* delims=  " %%a in ('"%~f0" LTrimInit') do (
  4.     if "%%a"=="" (echo;) else (
  5.         set "var=  %%a"
  6.         set /p="  %%a"<nul>"%temp%\~line.tmp"
  7.         for %%i in ("%temp%\~line.tmp") do (
  8.             if %%~zi gtr 60 (set size=%%~zi&call :split) else echo=  %%a
  9.         )
  10.     )
  11.     del "%temp%\~line*.tmp" >nul 2>nul
  12. )
  13. pause&exit/b
  14. :LTrimInit
  15. set "tab= "
  16. for /f "delims=" %%a in ('findstr /n .* a.txt') do (
  17.     set var=%%a
  18.     setlocal enableDelayedExpansion
  19.     set var=!var:%tab%= !
  20.     set var=!var:*:= !
  21.     echo=!var!
  22.     endlocal
  23. )
  24. goto :eof
  25. :split
  26. set offset=0
  27. setlocal enableDelayedExpansion
  28. fsutil file createnew "%temp%\~line2.tmp" !size! >nul
  29. for /f "tokens=2 delims=: " %%a in ('fc /b "%temp%\~line.tmp" "%temp%\~line2.tmp" ^| more +1') do (
  30.     set /a n+=1, n%%=60
  31.     if 0x%%a geq 128 (set /a byte+=1) else set /a byte+=2
  32.     if !n!==0 (
  33.         if 0x%%a geq 128 (
  34.             if 0x!prev! lss 128 (set /a "len=(byte-1)>>1", byte=1, n=1) else set /a "len=byte>>1", byte=0
  35.         ) else (
  36.            set /a "len=byte>>1", byte=0
  37.         )
  38.         for /f "tokens=1,2" %%i in ("!offset! !len!") do echo=!var:~%%i,%%j!
  39.         set /a offset+=len
  40.     )
  41.     set prev=%%a
  42. )
  43. if %n% neq 0 echo=!var:~%offset%!
  44. goto :eof
复制代码

作者: 523066680    时间: 2009-8-16 22:07

先重定向30个字符~ 然后再循环,但感觉效率不是高,没有继续
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. err>result.x 2>nul
  4. for /f "tokens=*" %%a in (text.txt) do (
  5. set a=%%a
  6. call :next
  7. )
  8. pause
  9. exit
  10. :next
  11. set /p x=%a:~0,30%>temp.x<nul
  12. set a=%a:~30%
  13.    :innext
  14.     for /f "tokens=3" %%a in ('dir temp.x /-c ^|find "个文件"') do (set num=%%a)
  15.     if %num% lss 60 (if not "%a%"=="" (
  16.     set /p x=%a:~0,1%>>temp.x<nul
  17.     set a=!a:~1!
  18.     goto :innext
  19.     ))
  20. type temp.x>>result.x
  21. echo,>>result.x
  22. if not "%a%"=="" (goto :next)
  23. goto :eof
复制代码

[ 本帖最后由 523066680 于 2009-8-16 22:08 编辑 ]
作者: PakTC    时间: 2009-8-18 16:33

支持特殊字符的 用了fsutil
  1. @echo off
  2. err>result.x 2>nul
  3. set /a x=0
  4. for /f "delims= eol=#" %%a in (text.txt) do (
  5.    set /a x+=1
  6.    set /a seta=0,setb=80
  7.    echo,    %%a>x.x
  8.    call :func
  9. )
  10. start result.x
  11. pause
  12. exit
  13. :func
  14.    echo,Sentence%x%
  15.    type x.x>temp.x
  16.    fsutil file setzerodata offset=0 length=%seta% temp.x     >nul
  17.    fsutil file setzerodata offset=%setb% length=10000 temp.x >nul
  18.    (for /f "delims= eol=#" %%c in ('more temp.x') do (echo,%%c>temp.x))||goto :eof
  19.    for /f "tokens=3" %%a in ('dir temp.x /-c ^|find "个文件"') do (set num=%%a)
  20.    set /a seta=seta+num-2,setb=seta+80 &type temp.x>>result.x &goto :func
  21. goto :eof
复制代码
处理的文本名称为 text.txt 下面是增加了字符串  "!!%%! !test!  的示例
3、接下来,你试着回答我一个问题批处理中最常用最复杂也是最强大的命令是哪个命令?

    相信经过以上两次的训练,你会脱口而出“for”。是的,for命令的确是批处理中最重要的命令,学好它的意义是不容置疑的。管理员就此命令特为大家精心撰写了for命令从入门到精通一贴,你所要做的就是前前后后将此贴通遍,将其搞懂弄明白,并结合大量的for命令练习,以熟练掌握for命令的各种应用。

                    至此,我可以说你已经脱菜了。但是不是掌握了for命令就可以“天下无敌,无坚不摧了呢”?非也,接下来,你还要继续提升自己。"!!%%! !test!


结果
    3、接下来,你试着回答我一个问题批处理中最常用最复杂也是最强大的命令是哪个命
令?
        相信经过以上两次的训练,你会脱口而出“for”。是的,for命令的确是批处
理中最重要的命令,学好它的意义是不容置疑的。管理员就此命令特为大家精心撰写了for
命令从入门到精通一贴,你所要做的就是前前后后将此贴通遍,将其搞懂弄明白,并结合大
量的for命令练习,以熟练掌握for命令的各种应用。
                        至此,我可以说你已经脱菜了。但是不是
掌握了for命令就可以“天下无敌,无坚不摧了呢”?非也,接下来,你还要继续提升自己
。"!!%%! !test!


[ 本帖最后由 PakTC 于 2009-8-18 16:38 编辑 ]
作者: zqz0012005    时间: 2009-8-18 22:43     标题: 回复 23楼 的帖子

  1. @echo off
  2. del "%temp%\~line*.tmp" >nul 2>nul
  3. if "%~1" neq "" goto LTrimInit
  4. for /f "eol= tokens=* delims=  " %%a in ('"%~f0" LTrimInit') do (
  5.     if "%%a"=="" (
  6.         for %%i in ("%temp%\~line.tmp") do (
  7.             for /f "usebackq delims=" %%A in (%%i) do if %%~zi gtr 60 (
  8.                 set var=%%A
  9.                 set size=%%~zi
  10.                 call :split
  11.             ) else (del "%temp%\~line.tmp" & echo=%%A)
  12.         )
  13.         echo;
  14.     ) else (
  15.         if not exist "%temp%\~line.tmp" (set /p="  %%a"<nul>>"%temp%\~line.tmp"
  16.         ) else set /p= %%a<nul>>"%temp%\~line.tmp"
  17.     )
  18. )
  19. rem 最后一段后面没有空行的情况
  20. if exist "%temp%\~line*.tmp" (
  21.     for %%i in ("%temp%\~line.tmp") do (
  22.         if %%~zi gtr 60 (
  23.             set size=%%~zi
  24.             for /f "usebackq delims=" %%A in (%%i) do set var=%%A
  25.             call :split
  26.         ) else echo=  %%a
  27.     )
  28. )
  29. pause&exit/b
  30. :LTrimInit
  31. set "tab=        "
  32. for /f "delims=" %%a in ('findstr /n .* a.bat') do (
  33.     set var=%%a
  34.     setlocal enableDelayedExpansion
  35.     set var=!var:%tab%= !
  36.     set var=!var:*:= !
  37.     echo=!var!
  38.     endlocal
  39. )
  40. goto :eof
  41. :split
  42. set offset=0
  43. setlocal enableDelayedExpansion
  44. fsutil file createnew "%temp%\~line2.tmp" !size! >nul
  45. for /f "tokens=2 delims=: " %%a in ('fc /b "%temp%\~line.tmp" "%temp%\~line2.tmp" ^| more +1') do (
  46.     set /a n+=1, n%%=60
  47.     if 0x%%a geq 128 (set /a byte+=1) else set /a byte+=2
  48.     if !n!==0 (
  49.         if 0x%%a geq 128 (
  50.             if 0x!prev! lss 128 (set /a "len=(byte-1)>>1", byte=1, n=1) else set /a "len=byte>>1", byte=0
  51.         ) else (
  52.            set /a "len=byte>>1", byte=0
  53.         )
  54.         for /f "tokens=1,2" %%i in ("!offset! !len!") do echo=!var:~%%i,%%j!
  55.         set /a offset+=len
  56.     )
  57.     set prev=%%a
  58. )
  59. if %n% neq 0 echo=!var:~%offset%!
  60. del "%temp%\~line*.tmp"
  61. goto :eof
复制代码
针对题目新要求做了改动,还需要完善。

[ 本帖最后由 zqz0012005 于 2009-8-18 22:50 编辑 ]




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