批处理之家's Archiver

batman 发表于 2009-12-11 10:25

【练习-054】用批处理选择性解析网页代码

出题目的:
    综合考查大家对文本的处理能力
加分原则:
    满分20分,视情况加分(以思路为重)
解题要求:
    代码高效、简洁、不生成临时文件
    另请技术组和管理层暂缓解题
题目如下:
    本人将论坛网页(我的评分)的一页源码复制到了a.txt(见附件),要求用批处理获取里面的被评分者、评分时间、
积分变动、评分理由信息,并生成b.txt如下(b.txt中所有信息都是从网页中获取的):[code]被评分者 评分时间 积分变动 评分理由
chenxin 09-12-10-12:27 PB-20 恶意编辑
chenxin 09-12-10-12:27 PB-20 恶意编辑
chenxin 09-12-10-12:26 PB-20 恶意编辑
chenxin 09-12-10-12:26 PB-20 恶意编辑
chenxin 09-12-10-12:26 PB-20 恶意编辑
chenxin 09-12-10-12:26 PB-20 恶意编辑
chenxin 09-12-10-12:25 PB-20 恶意编辑
chenxin 09-12-10-12:25 PB-20 恶意编辑贴子
bat_fan 09-12-10-09:59 PB+5 感谢分享
neorobin 09-12-9-15:25 PB+5 感谢分享
3Q3Q 09-12-9-10:47 PB-3 擅自修改标题并在标题上直呼人名
ljs4r 09-12-6-21:02 PB+2 感谢主动给标题标注[已解决]字样
ljs4r 09-12-4-09:05 PB+2 感谢主动给标题标注[已解决]字样
neorobin 09-12-3-08:49 技术+1 好规范的代码
neorobin 09-12-3-08:49 PB+20 好规范的代码
summerflower 09-11-30-12:25 PB+2 感谢主动给标题标注[已解决]字样
zjw767676 09-11-29-17:39 PB+5 说得对,论坛禁灌水
canyue 09-11-29-16:00 PB+2 感谢主动给标题标注[已解决]字样
summerflower 09-11-29-15:31 PB+2 感谢主动给标题标注[已解决]字样
terse 09-11-29-10:53 PB+40 好,只是晚到了点[/code]完成了上一步的可以提高难度,要求获取被评分者 帖子内容预览 评分者 评分时间 积分变动 评分理由信息,并生成b.txt如下:[code] 被评分者 帖子内容预览 评分者 评分时间 积分变动 评分理由
chenxin http://bbs.bathome.net/thread-6566-1-1.html batman 09-12-10-12:27 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6566-1-1.html batman 09-12-10-12:27 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:26 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:26 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:26 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:26 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:25 PB-20 恶意编辑
chenxin http://bbs.bathome.net/thread-6432-1-1.html batman 09-12-10-12:25 PB-20 恶意编辑贴子
bat_fan http://bbs.bathome.net/thread-6627-1-1.html batman 09-12-10-09:59 PB+5 感谢分享
neorobin http://bbs.bathome.net/thread-6655-1-1.html batman 09-12-9-15:25 PB+5 感谢分享
3Q3Q http://bbs.bathome.net/thread-6633-1-1.html batman 09-12-9-10:47 PB-3 擅自修改标题并在标题上直呼人名
ljs4r http://bbs.bathome.net/thread-6625-1-1.html batman 09-12-6-21:02 PB+2 感谢主动给标题标注[已解决]字样
ljs4r http://bbs.bathome.net/thread-6602-1-1.html batman 09-12-4-09:05 PB+2 感谢主动给标题标注[已解决]字样
neorobin http://bbs.bathome.net/thread-6592-1-1.html batman 09-12-3-08:49 技术+1 好规范的代码
neorobin http://bbs.bathome.net/thread-6592-1-1.html batman 09-12-3-08:49 PB+20 好规范的代码
summerflower http://bbs.bathome.net/thread-6541-1-1.html batman 09-11-30-12:25 PB+2 感谢主动给标题标注[已解决]字样
zjw767676 http://bbs.bathome.net/thread-6482-1-1.html batman 09-11-29-17:39 PB+5 说得对,论坛禁灌水
canyue http://bbs.bathome.net/thread-6534-1-1.html batman 09-11-29-16:00 PB+2 感谢主动给标题标注[已解决]字样
summerflower http://bbs.bathome.net/thread-6531-1-1.html batman 09-11-29-15:31 PB+2 感谢主动给标题标注[已解决]字样
terse http://bbs.bathome.net/thread-6467-1-1.html batman 09-11-29-10:53 PB+40 好,只是晚到了点[/code]注:[url=http://bbs.bathome.net/]http://bbs.bathome.net/[/url]这部分可自行加上去,计分同时提高到30分。
链接: [url]https://pan.baidu.com/s/1t4QIOnDCEPgmGmULIjdOug[/url] 提取码: nvqt

caruko 发表于 2009-12-11 17:43

原来跟我文本的版本不一样..=.=
加了个括号, 1,5,8 改1,5,8*
[code]@echo off
set /a n=0
for /f "delims=*" %%i in ('findstr /i /n "class=.time." a.txt') do (
        set "var=%%i"
        setlocal enabledelayedexpansion
        if !n! LEQ 0 (
            for /f "tokens=4 delims=:<>" %%a in ("!var!") do (
                set top=%%a
                set top=!top:/=      !
                echo !top!
              )
        )else (
            for /f "tokens=1,5,8* delims=:<>" %%a in ("!var!") do (
                set /a cow=%%a
                set "uname=%%b"
                set "pbdate=%%c"
                set "d=%%d"
                set "pbdate=!pbdate: =-!:!d:~0,2!"
                set/p=!uname! !pbdate! <nul
                call :getpb !cow!
              )
        )
        endlocal
        set /a n+=1
)
pause
goto :eof
:getpb
for /f "skip=%1 tokens=3,5 delims=<>" %%x in (a.txt) do (
    set /a l+=1
    if !l! EQU 1 (set/p=%%x%%y <nul )  else (
        set/p=%%x <nul
        echo,
        goto :eof
    )
)[/code]

[[i] 本帖最后由 caruko 于 2009-12-14 11:56 编辑 [/i]]

pumahxh 发表于 2009-12-11 20:37

没考虑太多代码效率等其它因素,发个先,后面再改进吧

[code]
@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%i in ('findstr "</td>" a.txt') do (
    set/a n+=1
    set str!n!=%%i
)
echo 被评分者 评分时间 积分变动 评分理由>b.txt
for /l %%i in (6,1,%n%) do (
    set/a num+=1
    set/a s=%%i%%5
    if !s! equ 1 (
       for /f "tokens=4 delims=<>" %%j in ("!str%%i!") do set/p=%%j  <nul>>b.txt)
    if !s! equ 3 (
       for /f "tokens=7 delims=<>" %%k in ("!str%%i!") do set/p=%%k  <nul>>b.txt)
    if !s! equ 4 (
       for /f "tokens=5 delims=<>" %%l in ("!str%%i!") do set/p=%%l  <nul>>b.txt)
    if !s! equ 0 (
       for /f "tokens=3 delims=<>" %%m in ("!str%%i!") do echo %%m>>b.txt)

)
pause
[/code]

[[i] 本帖最后由 pumahxh 于 2009-12-11 20:41 编辑 [/i]]

batman 发表于 2009-12-12 09:44

回复 3楼 的帖子

1、结果肯定不是很正确,时间的输出格式是09-12-4-09:05,PB的输出应该是PB+5式样(都要处理其中的空格)。

2、我在顶楼要求b.txt中所有信息都要从网页源码中获取,即你并不知道要提取的信息具体内容,所以echo 被评分者 评分时间 积分
变动 评分理由>b.txt有点投机了。

3、效率上是存在着一定的问题,具体也不多说了。

4、总之完成的还可以,继续加油!

batman 发表于 2009-12-12 17:35

回复 2楼 的帖子

if !l! EQU 1 set/p=%%x%%y <nul  else ( 这是什么语法?

另结果不正确。。。

batman 发表于 2009-12-12 17:45

&&我之所以在顶楼要求技术组和管理层暂不解题,就是想留给大家更多独立思考的时间,所以请大家都动脑想一想,动手练一练,

同时这样的问题你们在现实中是很有可能遇到的,只要独立解出了此题,相信以后你们碰到同样的问题,处理起来一定会得手应手。

Seter 发表于 2009-12-12 18:46

从15:00做到19:00...chenxin的OK了后面的不行吖....汗
无语,我讨厌大型数据

batman 发表于 2009-12-12 19:18

回复 7楼 的帖子

依我的理解,应该不会出现兄弟这样的情况,不知兄弟用的是什么方法,逐行判断处理?

pumahxh 发表于 2009-12-12 20:04

谢谢楼主出的好题

楼主的题目非常好,在实际工作中很有借鉴意义,希望高手暂缓出手,等我们写完了,你们再指点,给出更好的解法。谢谢大家!

batman 发表于 2009-12-12 20:40

做点小小的提示:

    1、充分利用findstr的正则来解题。

    2、尽量采用一次性读取和输出以提高效率,即读取和输出同时进行。

    3、在获取链接地址时注意处理引号技巧的运用。

pumahxh 发表于 2009-12-12 22:32

按要求改进后的,感觉代码比较繁琐,请LZ指导

[code]@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%i in ('findstr /i "</td> <b><a" a.txt') do (
    set/a n+=1
    set str!n!=%%i
)
for /l %%i in (1,1,5) do (
    for /f "tokens=3 delims=<>" %%j in ("!str%%i!") do set "T=%%j"&set "T=!T:/=   !"
    set/p=!T! <nul>>b.txt   
)
echo.>>b.txt
for /l %%i in (6,1,%n%) do (
    set/a s=%%i%%6
    if !s! equ 0 (
       for /f "tokens=4 delims=<>" %%j in ("!str%%i!") do set/p=%%j  <nul>>b.txt)
    if !s! equ 1 (
       for /f "tokens=8 delims== " %%k in ("!str%%i!") do set/p=http://bbs.bathome.net/%%~k  <nul>>b.txt)
    if !s! equ 3 (
       for /f "tokens=4,7 delims=<>" %%l in ("!str%%i!") do (
                 set/p=%%l  <nul>>b.txt
                 set dt=%%m
                 set dt=!dt: =-!
                 set/p=!dt!  <nul>>b.txt))
    if !s! equ 4 (
       for /f "tokens=3,5 delims=<>" %%m in ("!str%%i!") do (
                 set pb=%%m
                 set pb=!pb: =!
                 set/p=!pb!%%n  <nul>>b.txt))
    if !s! equ 5 (
       for /f "tokens=3 delims=<>" %%n in ("!str%%i!") do echo %%n>>b.txt)

)
pause[/code]

pumahxh 发表于 2009-12-12 23:23

[quote]原帖由 [i]batman[/i] 于 2009-12-12 20:40 发表 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=43419&ptid=6674][img]http://www.bathome.net/images/common/back.gif[/img][/url]
做点小小的提示:

    1、充分利用findstr的正则来解题。

    2、尽量采用一次性读取和输出以提高效率,即读取和输出同时进行。

    3、在获取链接地址时注意处理引号技巧的运用。 [/quote]
请问LZ,你提到的提示第2点:读出和输出同时进行,是什么意思?是读出a.txt的信息时,同时输出b.txt吗?在一个for语句中进行?
在获取链接地址时,我用"delims=""或"delims="""都得不到地址,最后用"delims= "才得到,特别是用"delims=""还报错!
用一个for一边读取一边输出,我改了下代码,不知是不是这样,但在程序开头和结尾加echo %time%来测算时间,和我前一种方法时间看不出差别。
[code]@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%i in ('findstr /i "</td> <b><a" a.txt') do (
    set/a n+=1
    if !n! lss 6 (
           for /f "tokens=3 delims=<>" %%j in ("%%i") do set "T=%%j"&set "T=!T:/=   !"
           set/p=!T! <nul>>b.txt   
           if !n! equ 5 echo.>>b.txt) else (
    set/a s=!n!%%6
    if !s! equ 0 (
       for /f "tokens=4 delims=<>" %%j in ("%%i!") do set/p=%%j  <nul>>b.txt)
    if !s! equ 1 (
       for /f "tokens=8 delims== " %%k in ("%%i!") do set/p=http://bbs.bathome.net/%%~k  <nul>>b.txt)
    if !s! equ 3 (
       for /f "tokens=4,7 delims=<>" %%l in ("%%i!") do (
                 set/p=%%l  <nul>>b.txt
                 set dt=%%m
                 set dt=!dt: =-!
                 set/p=!dt!  <nul>>b.txt))
    if !s! equ 4 (
       for /f "tokens=3,5 delims=<>" %%m in ("%%i!") do (
                 set pb=%%m
                 set pb=!pb: =!
                 set/p=!pb!%%n  <nul>>b.txt))
    if !s! equ 5 (
       for /f "tokens=3 delims=<>" %%n in ("%%i!") do echo %%n>>b.txt)
                 )
)
pause[/code]

[[i] 本帖最后由 pumahxh 于 2009-12-12 23:24 编辑 [/i]]

asnahu 发表于 2009-12-12 23:59

[code]@echo off&setlocal enabledelayedexpansion
echo 被评分者        评分时间        积分变动   评分理由
for /f "skip=6 delims=" %%i in ('findstr "td" _a.txt') do (
        set /a n+=1
        set var=!var!%%i
        if !n!==6 (
                set foo=!var!
                set foo=!foo: =!
                set foo=!foo:        =!
                for /f "tokens=3,13,16,18,22 delims=<>" %%a in ("!foo!") do (
                        set flag=%%b
                        call:sub %flag%
                        call,echo/%%a        %%flag%%      %%c%%d    %%e
                )
                set var=
                set n=0
        )
)
pause>nul

:sub
set dt=%flag:~,-5%
set tm=%flag:~-5%
set "flag=%dt% %tm%"
goto :eof[/code]

[[i] 本帖最后由 asnahu 于 2009-12-13 09:04 编辑 [/i]]

batman 发表于 2009-12-13 09:38

回复 13楼 的帖子

1、论坛是不能处理tab的,所以贴出带有tab的代码时,最好要说明下哪些空格实际上tab。

2、echo 被评分者        评分时间        积分变动   评分理由违反题意。

3、既然开了变量延迟为什么还要用call,这样会代码运行影响效率。

4、时间中的空格没有处理好。

5、这种长变量的方法很好,思路好。

batman 发表于 2009-12-13 09:50

回复 12楼 的帖子

之所以看不出你上下两段代码的效率的区别,我想原因有二:

1、你12楼的代码中有大量的冗余操作,导致代码效率降低。

2、处理的数据量不是很大,所以在时间比较上看不出太大的差别。

batman 发表于 2009-12-13 14:08

&&看来此题对于普通会员来说具有一定的难度,下面给出本人的全解,并稍做说明,代码如下:[code]@echo off&setlocal enabledelayedexpansion
(for /f "delims=" %%a in ('findstr /r "<b>< <td.*d>$" a.txt') do (
    set /a n+=1&if !n! equ 6 set /a n=1,m=0&echo.
    if not defined m (
       for /f "tokens=3,4 delims=/<>" %%b in ("%%a") do set /p=%%b <nul&if !n! equ 3 set /p=%%c <nul
       ) else (
       if !n! equ 1 for /f "tokens=4 delims=<>" %%b in ("%%a") do set /p=%%b <nul
       if !n! equ 2 for /f "tokens=8 delims== " %%b in ("%%a") do set /p=http://bbs.bathome.net/%%~b <nul
       if !n! equ 3 for /f "tokens=8,12,13 delims=<> " %%b in ("%%a") do set /p=%%b %%c-%%d <nul
       if !n! equ 4 for /f "tokens=4,7 delims=<> " %%b in ("%%a") do set /p=%%b%%c <nul
       if !n! equ 5 for /f "tokens=3 delims=<>" %%b in ("%%a") do set /p=%%b <nul
    )
))>b.txt
start b.txt[/code]说明:
    首先讲讲findstr正则的运用,大家都明白代码中运用findstr是为了最大限度地从a.txt中剔除无用信息行而提取有用信息行,所以

代码中使用了findstr /r "<b>< <td.*d>$" a.txt,之所以使用/r参数是为了让findstr识别后面的<td.*d>$表达式而不是全做为字符来处理

其中的$表示行尾,使用<b><的表达式的意思大家都知道我就不说明了,使用<td.*d>$表达式就可以提取所有含有<td字符并从中剔

除只以<td>结尾的行。

    接下来讲下代码中for /f "tokens=* delims=*"的运用,使用findstr正则提取了有用信息行后,接下来我们还要从每行中剔除无用

的信息,而保留输出想要的信息,一般来说可以采用两种办法,一种是字符截取,但因为文本中的字符数是在变化的,所以此法不

可用,那么我们就要利用好for /f中的tokens和delims参数了,先选取合适的足够的分隔符来将每行分成n列,注意在分隔时不要将

我们想要获取的字符部分分开了,同时尽量取特殊字符为分隔符而不要取常用的数字和字母,最后取我们所需要的列并输出就可以

了。

   看了13楼的长变量法(将每五行存入一个变量),我也尝试过用此法来解析出全信息,但实际上处理起来相当麻烦,希望有高人

能给出此法的精彩代码。

terse 发表于 2009-12-13 15:54

学习了[code]@echo off&setlocal enabledelayedexpansion
set "s=http://bbs.bathome.net/"
(for /f "tokens=3,4,5,7 delims=<>" %%a in ('findstr /r "<b>< <td.*d>$" a.txt') do (
    set /a n+=1
        if !n! gtr 5 (
           if /i "%%c" equ "/a" (
           if "%%d" neq "" (
           for /f "tokens=1-3 delims== " %%i in ("%%d") do (
              if "%%k" neq "" (set str=!str! %s%%%~k)else set "str=!str! %%b %%i-%%j"
           )
           ) else echo!str!&set "str= %%b"
           ) else (
             if /i "%%c" neq "" (
             for %%i in (%%a) do set "str=!str! %%i%%c"
            )else set str=!str! %%a
           )
         ) else for /f "tokens=1,2 delims=/" %%i in ("%%a") do (
           if "%%j" equ "" (set str=!str! %%i)else set "str=!str! %%i %%j"
         ))
         echo!str!)>b.txt
pause[/code]

Seter 发表于 2009-12-13 16:44

[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=1 delims=:" %%i in ('findstr /n """ratelogviewer""" a.txt') do set n=%%i
set/an+=2
for /f "skip=%n% tokens=2-3 delims=^<^>" %%i in (a.txt) do (
if [%%j]==[] goto out
set j=%%j
set/p=!j:/= ! <nul
)
:out
echo.
set/an+=9
for /f "eol=[ skip=%n% tokens=2-7 delims=^<^>" %%i in (a.txt) do (
set/ai+=1
if !i!==2 set/p=%%k <nul
if !i!==4 set j=%%j&set j=!j:"=,!&for /f "tokens=2 delims=," %%z in ("!j!") do set/p=http://bbs.bathome.net/%%z<nul
if !i!==7 set/p=%%k %%n <nul
if !i!==8 set/p=%%j %%l <nul
if !i!==9 set/p=%%j<nul
if !i!==10 set i=0&pause
)[/code]让我郁闷的代码

batman 发表于 2009-12-13 17:11

回复 18楼 的帖子

看了你的代码,我也着实郁闷,你处理得太复杂了吧,后面的结果根本不对。。。

caruko 发表于 2009-12-14 08:45

[quote]原帖由 [i]batman[/i] 于 2009-12-12 17:35 发表 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=43398&ptid=6674][img]http://bbs.bathome.net/images/common/back.gif[/img][/url]
if !l! EQU 1 set/p=%%x%%y  [/quote]

这个是去掉PB后面的空格.. 只不过都是输出到控制台,没>>B.TXT
本地运行正常啊...晕,昨天日期格式还正确的,今天就.... if 后也还得加个括号了

就是findstr /n 得到每个class=time(除了第一个time)的cow,然后for /f skip=cow 来取得后续几个元素
%l% 的值代表class=time 下面的第几行
因为 被评分者 看错成评分者了,所以 只取了2次就goto :eof
不过 帖子地址,被评分者 分别是%l%=5 ,6 时的行,稍扩展一下也能达到新的要求

[[i] 本帖最后由 caruko 于 2009-12-14 11:48 编辑 [/i]]

batman 发表于 2009-12-14 17:58

回复 20楼 的帖子

像这种逐行(实际上不是每行)skip的方法,效率是最大的问题,如果有10000组数据要处理,那岂不是要用for

对文本读取10000次,还有被评者是在每组第一行的,请问用这种skip方法如何得到?就是经处理得到后,还不是

一样要处理滤过每组的第二行?再说了对空格的处理直接用delims不就行了,还要搞什么退格?

caruko 发表于 2009-12-15 08:53

回上..
效率确实不高 =.= 因为第2次读了文本
只不过对findstr不太熟,设计了几个复杂点的正则,结果都不对..

neorobin 发表于 2009-12-18 13:11

按效率, 代码简洁度, 格式适应度给出 3 个版本:

楼主的代码果然厉害, 又简短, 又高效, 学习!
对于 findstr, 尚在学习, 一开始思路也想到这个, 但终不熟悉于是换了方向
[color=red][b]以下所有代码中 delims= 的后面直到 " 之间的若干空格其实都是一个 TAB 字符和一个半角空格, 复制代码请再替换一下, 看了 14 楼的提醒才知道论坛有这个问题[/b][/color]
[b]效率版[/b](效率优先, 对 a.txt 文件格式变动适应差, 代码简洁度其次考虑)[code]@echo off & setlocal enabledelayedexpansion
for /f "eol=[ skip=69 delims=" %%a in (a.txt) do (
  if "!doneHead!"=="" (
        for /f "tokens=1-4 delims=></         " %%b in ("%%a") do (
          if /i "%%c"=="class="time"" (set ln=!ln! %%d %%e) else (         
            if "%%b"=="tbody" (echo !ln:~1!>b.txt)&(set doneHead=done)&(set lnBeratedOffs=-3) else (         
                  if /i "%%b"=="td" set ln=!ln! %%c
  ) ) ) ) else ( set /a "lnBeratedOffs+=1"
    if !lnBeratedOffs! equ 0 (
          for /f "tokens=1 delims=<>         " %%b in ("%%a") do if /i "%%b"=="/table" (
            (start b.txt)&(if exist b样本.txt comp b样本.txt b.txt /l)& exit /b
          ) else for /f "tokens=7 delims=&>?<         " %%z in ("%%a") do set ln=%%z
        ) else if !lnBeratedOffs! equ 2 (
          (set search=sTime)&(for /f "tokens=8 delims==         " %%b in ("%%a") do set ln=!ln! http://bbs.bathome.net/%%~b)
        ) else if !lnBeratedOffs! geq 6 (
          if "!search!"=="sTime" (  
            for /f "tokens=2,6,10,11 delims=<>         " %%b in ("%%a") do (
                  if /i "%%b"=="class="time"" (set ln=!ln! %%c %%d-%%e)&set search=bold)
      ) else if "!search!"=="bold" (
        (set search=cause)&(for /f "tokens=2,5 delims=<>         " %%b in ("%%a") do set ln=!ln! %%b%%c)
          ) else if "!search!"=="cause" (
            (set search=wait)&(set lnBeratedOffs=-3)&(for /f "tokens=2 delims=<>         " %%b in ("%%a") do echo !ln! %%b>>b.txt)
) ) ) )[/code][b]简洁版[/b](以代码简洁优先, 效率及适应性考虑次之)[code]@echo off & setlocal enabledelayedexpansion
for /f "eol=[ skip=69 delims=" %%l in (a.txt) do (
  if "!doneHead!"=="" (
    for /f "tokens=1-4 delims=></         " %%A in ("%%l") do (
      if /i "%%A"=="tbody" (set doneHead=done)&(echo !ln:~1!>b.txt) else (
            if /i "%%B"=="class="time"" (set ln=!ln! %%C %%D) else if /i "%%A"=="td" (set ln=!ln! %%B)
    ) )
  ) else for /f "tokens=1-17 delims==&?></         " %%A in ("%%l") do (
    if /i "%%A"=="tbody" (start b.txt)&(if exist b样本.txt comp b样本.txt b.txt /l)& exit /b
    if /i "%%F"=="berated" (set ln=%%K http://bbs.bathome.net/)
    if /i "%%K%%L"=="ahref" (set ln=!ln!%%~M) else if /i "%%L%%M"=="ahref" (set ln=!ln!%%~N)
    if /i "%%C"==""time"" (set ln=!ln! %%M %%P-%%Q)
    if /i "%%E"==""bold"" (set ln=!ln! %%B%%F)
    if /i "%%C"=="td" echo !ln! %%B>>b.txt
) )[/code][b]适应版[/b](起始不采用跳过指定行数, 而是根据搜索特定字符串找到记录表头, 适应 a.txt 文件格式变动略好)[code]@echo off & setlocal enabledelayedexpansion
for /f "eol=[ delims=" %%a in (a.txt) do (
  if "!doneHead!"=="" (
    for /f "tokens=2 delims=         " %%b in ("%%a") do if /i "%%b"=="summary="ratelogviewer"" (set doneHead=doing)
  ) else if /i "!doneHead!"=="doing" (
        for /f "tokens=1-4 delims=></         " %%b in ("%%a") do (
          if /i "%%c"=="class="time"" (set ln=!ln! %%d %%e) else (
            if "%%b"=="tbody" (echo !ln:~1!>b.txt)&(set doneHead=done)&(set lnBeratedOffs=-3) else (
                  if /i "%%b"=="td" set ln=!ln! %%c
    ) ) )
  ) else ( set /a "lnBeratedOffs+=1"
    if !lnBeratedOffs! equ 0 (
          for /f "tokens=4,7 delims=&>?<         " %%b in ("%%a") do (set ln=%%c)
        ) else if !lnBeratedOffs! equ 2 (
          for /f "tokens=8 delims==         " %%b in ("%%a") do (set ln=!ln! http://bbs.bathome.net/%%~b)
        ) else if !lnBeratedOffs! geq 6 (
          for /f "tokens=1-6,10,11 delims=<>         " %%b in ("%%a") do (
                if /i "%%c"=="class="time"" (set ln=!ln! %%g %%h-%%i) else (
                  if /i "%%e"=="class="bold"" (set ln=!ln! %%c%%f) else (
                    if /i "%%d"=="/td" (echo !ln! %%c>>b.txt) else (
                          if /i "%%b"=="tr" (set /a "lnBeratedOffs=-1") else if /i "%%b"=="/tbody" (
                            (start b.txt)&(if exist b样本.txt comp b样本.txt b.txt /l)& exit /b
) ) ) ) ) ) ) )[/code]

[[i] 本帖最后由 neorobin 于 2009-12-18 15:22 编辑 [/i]]

neorobin 发表于 2009-12-18 20:37

回复 16楼 的帖子

不知楼主设想的变量法是怎样的
findstr + 大变量, 代码中的 ★ 代表 TAB 字符, 请复制后作相应替换[code]@echo off&setlocal enabledelayedexpansion & cd.>b.txt & (set /a ii=-1)
(for /f "delims=" %%a in ('findstr /r "<b>< <td.*d>$" a.txt') do (
  (set ln=!ln!%%a)&(set /a "ii+=1,ii%%=5")
  if not defined doneHead (
        if !ii! equ 4 for /f "tokens=2,5,9,10,13,16 delims=></★ " %%A in ("!ln!") do (
      set ln=%%A %%B %%C %%D %%E %%F)
  ) else if !ii! equ 4 (
    for /f "tokens=1,2,8,12-13,16,19,23 delims=<>★ " %%A in ("!ln!") do set ln=%%A %%B %%C %%D-%%E %%F%%G %%H
  ) else ( if !ii! equ 1 for /f "tokens=9,23 delims==<>★ " %%A in ("!ln!") do (
          set ln=%%A http://bbs.bathome.net/%%~B
  ) )
  if !ii! equ 4 (set /p=!ln!<nul& echo.)&(set doneHead=yes)&(set ln=)
)>>b.txt) & (start b.txt)&(if exist b样本.txt comp b样本.txt b.txt /l)& exit /b[/code]

[[i] 本帖最后由 neorobin 于 2009-12-18 20:46 编辑 [/i]]

batman 发表于 2009-12-18 21:40

回复 24楼 的帖子

我所说的大变量法在前面16楼已经说明了,但要求比我16楼的代码还要简洁,目前苦无突破。。。

qzwqzw 发表于 2011-3-13 19:42

回复 25楼 的帖子

这是结合13楼与16楼的特点的一个解法
将每五行文本连接拼成一个变量
为了规避for的32个tokens的限制
替换了空格、TAB和/A
为了解决双引号不能同时与其它字符做分隔符的问题
替换了双引号为单引号[code]@echo off&setlocal enabledelayedexpansion
(echo 被评分者 帖子内容预览 评分者 评分时间 积分变动 评分理由
for /f "skip=5 delims=" %%i in ('findstr /r "pid= <td.*/td>$" a.txt') do (
        set /a n+=1
        set var=!var!%%i
        if !n!==5 (
                set foo=!var: =!
                set foo=!foo:        =!
                set foo=!foo:"='!
                set foo=!foo:/a=!
                for /f "tokens=6,9,19,21,24,27,31 delims=<>'" %%a in ("!foo!") do (
                        set url=http://bbs.bathome.net/%%b
                        set ratetime=%%d
                        echo.%%a !url:amp;=! %%c !ratetime:~0,-5!-!ratetime:~-5! %%e%%f %%g
                )
                set var=
                set n=0
        )
))>b.txt
start b.txt[/code]

[[i] 本帖最后由 qzwqzw 于 2011-3-13 19:53 编辑 [/i]]

我来了 发表于 2016-9-30 05:07

你们不会善于使用 论坛 的功能 为关键代码着色
findstr 详细使用,书中有过记载的

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.