Board logo

标题: 批處理室 管理日志 [打印本页]

作者: willsort     时间: 2006-4-26 18:59    标题: 批處理室 管理日志

To All:

本版块正在整理中,为了不影响版面秩序,请各位暂转向解答室或教学室发表新帖或回复。整理期限暂定为十天!

根据Wengier的意见,取消本版块整理期间的发帖和回帖限制

[ Last edited by willsort on 2006-4-27 at 22:35 ]
作者: Wengier     时间: 2006-4-27 00:49
向无奈何提出邀请后,无奈何提出愿意作为副版主协作willsort的工作。大家一起合作吧。
作者: 无奈何     时间: 2006-4-27 21:02
签个到。先说明一下,我的管理能力很差,业务水平也很有限,因为我感兴趣并涉猎的范围很窄。既然顶起副版之名,我会尽力协助 willsort 兄做好工作。我也由衷地希望这个版块慢慢的热闹起来。
作者: willsort     时间: 2006-4-27 21:24
Re 无奈何:

      感谢兄对论坛发展的热心,希望你我能够共同维护好这个版块。

      现在本版的整理计划分为三个步骤:

      1、将其他各版区的批处理和脚本技术主题转移过来,重点是已结主题;

      2、按主题内容标记转移过来的主题为已结、精华等;

      3、整理出本版的精华主题和已结主题分类索引;

      4、整理出一份比较简单的FAQ和比较全面的讨论文集;

      5、制作出FAQ和文集的chm/txt/html版,并定期更新;

      对以上计划,请兄提供一些意见和建议,最好能提供一些快速实现的方案,我花了许多时间寻找了一些工具,结果都很不理想:Discuz!探索者不支持Unicode,curl至今未找到登录本论坛的命令行参数,不知兄对此有何建议?

[ Last edited by willsort on 2006-4-27 at 21:50 ]
作者: 无奈何     时间: 2006-4-28 00:07
To willsort
我没有管理论坛的经验,所以现在很难知道或找到一些有效管理的方法。我现在没有操作其它版块的权限,当然这也是好事,可以避免错误的操作。所以转移相关主题帖由兄来完成吧,我负责整理一下 FAQ 吧!

关于快速实现整理方案,我可以将相关的主题下载到本地然后整理成文本。
关于 curl 的使用你可以登录一次论坛用嗅探软件(如:HTTPLook、WinSock Expert等)截取提交的信息。
然后用 curl 提交并保存为 cookies ,下次提交 cookies 就行了。
如:

  Quote:
curl -c cookies.txt "http://www.cn-dos.net/forum/logging.php?action=login&&referer=http%3A%2F%2Fwww.cn-dos.net%2Fforum%2Fforumdisplay.php%3Ffid%3D22&loginmode=&styleid=&cookietime=31536000&username=用户名&password=密码&questionid=3&answer=回答&loginsubmit=安全提问"
curl -b cookies.txt "http://www.cn-dos.net/forum/viewthread.php?tid=20332&fpage=1" -o out.html

因为论坛所用编码问题,第一条命令无论如何都不能得到正确的 cookies ,可将红色部分替换为嗅探到的对应部分。
然后加载 cookies 就可以用登录名操作了。
不知道通过提交 post表单 等其它的参数可否实现批量转移,由于无法验证所以只能是猜想。
作者: 无奈何     时间: 2006-4-28 01:59
收集了一下已结贴的信息。
见附件
附件 1: 已结贴.zip (2006-4-28 01:59, 1.61 K, 下载附件所需积分 1 点 ,下载次数: 21)

作者: Wengier     时间: 2006-4-28 12:43
现在3742668也接受了willsort的邀请,愿意协助处理。
作者: 3742668     时间: 2006-4-28 13:30
报告:
   编号3742668前来报道,请多多指教!

有什么需要我帮忙的?
作者: willsort     时间: 2006-4-28 21:02
Re 无奈何:

      已结帖信息大致浏览了一下,大部分是解答室中我曾经标注过的已结主题,要向本版转移还需要针对批处理分类作进一步过滤和增补。我做过一些简单的正则表达式的过滤尝试,对链接地址的过滤效果很不理想。如果你可以将过滤搜索页面的脚本共享出来,可以考虑在此基础上修改脚本,使之生成批量管理页面的本地定制版。

      HTTPLook、WinSock Expert等还未尝试,等明天测试再报告结果吧。

Re 3742668:

      欢迎你的加入!

      本版的整理计划已经在4楼公开了,因为各步计划之间有较强的顺序性,因此如果你有其他版面的管理权限,可以考虑将批处理主题的转移任务分成两部分,你我各则负责一部分。

      当然,也可以根据自己的爱好和想法,选择自己的任务,提出自己的建议,让大家讨论一下。

[ Last edited by willsort on 2006-4-29 at 00:09 ]
作者: 无奈何     时间: 2006-4-29 00:57
To willsort
      已结帖绝大部分都是DOS疑难解答版的,哈哈,足可见兄的勤勉。
      关于帖子链接整理的脚本,我努力了很长时间也没有能在单个的脚本里完成。我写的很粗糙,权当应急之用,希望有达人能给完善一下。
      需要两步来:
CODE:  [Copy to clipboard]
     
      sed -f html.sed *.html >temp.txt
     sed -e :a -e "N;s/\n/\t/;ta" temp.txt| sed -e "s/\t\+/\t/g;s#[\t]*\(viewthread.php\)#\nhttp://www.cn-dos.net/forum/\1#g">out.txt
html.sed
CODE:  [Copy to clipboard]
#n
/viewthread.php?tid=/,/^<table cellpadding="0"/{
/viewthread.php/{s#^.*\(viewthread.php?tid=[0-9]\+\)[^>]\+ >\([^<]\+\).*#\1\t\2#}
s#<[^>]\+>##g
p
}
事先需要将搜索到的网页下载到本地,用 curl 很方便;然后转换文件编码,推荐使用 ConvertZ ,有命令行版本。
作者: willsort     时间: 2006-4-29 11:56
Re 无奈何:

      刚试过HttpLook 1.25,很可惜的是,我的新装系统,一旦安装它之后,就无法正常浏览网页,使用访问快速启动栏的IE快捷方式无法打开IE,进程管理器可以观察到IEXPLORE.EXE,系统反映明显迟钝;通过开始菜单的IEIE命令可以打开,此时访问任何链接都提示无法浏览页面,从状态栏观察似乎没有访问dns服务器;重启计算机后本地链接变成受限制,而且无法修复。卸载改软件后问题消失。

     你的脚本我试用后再做回复。如果最后这个脚本可以修改成生成批量管理的本地页面,那么我可以选择不用curl,而是使用IE登陆论坛后,再打开本地页面提交管理请求。
作者: 无奈何     时间: 2006-4-29 22:28
To willsort
        HttpLook 1.25 在我 2K3 下没有任何问题,以前在 XP 下用 HttpLook 监听时偶尔会有网页打不开,停止监听也就解决了。你可以试试 WinSock Expert 只是部分杀软会报为病毒,或者尝试其它软件代替。
        重新用 GAWK 写了帖子链接整理的脚本,发觉比用 SED 好写的多。兼容性增强了一点,不仅支持搜索页面,还兼容了主题页面。我的处理流程如下:
        1、嗅探得到登录地址,用 curl 获取 cookies。
        2、用 curl 下载所要的搜索、主题页面。
        3、用 ConCmd (ConvertZ的命令行版)转换网页编码。
        3、用 GAWK 脚本过滤出帖子标题、链接等信息。

        所需软件链接:
        curl:http://curl.haxx.se/download.html
        concmd:http://alf-li.pcdiscuss.com/files/concmd15.zip
        gawk:http://www.klabaster.com/progs/gawk32.zip
        html.awk
CODE:  [Copy to clipboard]
/^[ \t]*<a href="viewthread.php/,/^[ \t]*<a href="viewpro.php/{
        if ($0~/^[ \t]*<a href="viewthread.php/){
                data=gensub(/^[ \t]*[^>]*(viewthread.php\?tid=[0-9]*)[^>]*>(.*)/,"\\1\t\\2","g",gensub(/<\/a>.*/,"","g"))
        }
        if ($0~/^[ \t]*<a href="viewpro.php/){
                data=data "\t" gensub(/[ \t]*<[^>]*>/,"","g")
                #获取匹配行其后3行内容
                line=3
                while(line--){
                        getline i
                        data=data "\t" gensub(/[ \t]*<[^>]*>/,"","g",i)
                }
                #作最后全局替换
                data="http://www.cn-dos.net/forum/" data
                data=gensub(/&lt;/,"<","g",data)
                data=gensub(/&gt;/,">","g",data)
                data=gensub(/&amp;/,"&","g",data)
                data=gensub(/&quot;/,"\"","g",data)
                data=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",data)
                print data
        }
}
修正了一下替换表达式,并增加了几个 HTML 特殊字符的处理 ,现在效果基本令人满意了。

[ Last edited by 无奈何 on 2006-5-1 at 00:52 ]
作者: willsort     时间: 2006-4-30 02:35
Re 无奈何:

      WinSock Expert在关闭杀毒软件监视后可以正常使用,但是因为缺乏对于http的了解,对嗅探到的信息似懂非懂,其中的send方法基本无可用信息,在某些获取图片的Get方法中倒是有一些与cookie类似的信息,但是始终无法据此组合出可以登陆论坛的命令行。

      sed的脚本看过了,但是因为我这里无法获得curl抓取的搜索页面,因此只能使用IE另存的搜索页面测试,但是这个页面中许多链接都是跨行的,你的脚本html.sed没有考虑到这些,而我也尝试了sed的一些跨行链接处理方法,在命令行脚本中有效,但是在脚本文件中始终无法得到正确的移植。

      你的awk脚本刚看到,似乎也没有针对跨行链接进行处理。
作者: 无奈何     时间: 2006-4-30 14:47
To willsort
        我晕,看看 IE 都干了什么!你用 FlashGet 等下载软件下载就不会出现跨行链接了。 FlashGet 支持使用 IE cookies,也可以批量下载,在设置项中设置为自动更名。
        对于网路协议我也知之甚少。你可以把 POST 中将 Referer: 部分地址与最后一行用 & 联接,就得到地址了。
作者: willsort     时间: 2006-5-3 23:32
Re 无奈何:

      根据兄的awk脚本修改出了一个转换搜索页面为本地批量移动页面的脚本,并据此尝试移动了开发室中以“批处理”和“bat”为关键字的大部分主题。所有相关文件在附件 bm_cnv.rar 中提供。

      明天将会很忙,请兄检查一下脚本是否存在什么漏洞,还有时间和权限的话,可以考虑移动一下“下载室”中的批处理主题。

      附件中\pages\的页面来自Opera的另存功能,FlashGet中并未找到有关cookie的选项,不过它支持在登陆后的IE页面中下载链接页面。

      临时文件movehead.tmp 和 movetail.tmp 截取自论坛主题列表下提供的批量移动功能所产生的页面,修改了网页编码、移动源版块、移动目的版块,表格列宽度略有调整,另外还精简了页面中的一些冗余信息。

      awk脚本的修改,主要是为产生批量移动页面所需要的表格而做出的;还有一些正则表达式的调整,主要是为了兼容主题标题中的<>符号,标题前夹杂图片链接,标题后含有多页面链接等异常情况而做出的。
CODE:  [Copy to clipboard]
:: cv.bat - Convert search pages to batch move pages of cn-dos forum
:: Will Sort - V4 - 2006-05-03 - CMD@WinXP
:: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
@echo off
concmd /i:utf8 /o:gbk ..\pages\%1*.htm? *.txt
gawk "/^#-- start/{x=1;next};/^#-- end/{x=0};x" %0 | gawk -f - %1*.txt? > out.txt
copy /b ..\movehead.tmp+out.txt+..\movetail.tmp _bm.html
copy _bm.html ..\pages\%1_bm.html
goto end

#awk srcipt: convert cn-dos forum serach page to plain text form
#-- start of awk script -------------------------------------------------------
/viewthread/,/viewpro/{
        if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
                sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
                sTitle=gensub(/.*\?tid=[0-9]*\&fpage=[^>]*>([^<]*)<\/a>.*/,"\\1","g")
        }
        if ($0~/viewpro/){
                sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                sDate=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                iReply=gensub(/[ \t]*<[^>]*>/,"","g")+0
                getline
                iView=gensub(/[ \t]*<[^>]*>/,"","g")+0
                iNo2=iNo2+1
                #if (iReply>=5 || iView>=50) {
                        iNo1=iNo1+1
                        data="<tr><td><input type=\"checkbox\" name=\"moderate[]\" "
                        data=data "value=\"" sTid "\" checked></td>"
                        data=data "<td><a href=viewthread.php?tid=\"" sTid "\">"
                        data=data "[" iNo1 "-" int((iNo2-1)/30)+1 ":" (iNo2-1)%30+1
                        data=data "-" sTid "]" sTitle "</a></td><td>" sAuthor "</td>"
                        data=data "<td>" sDate "</td><td>" iReply "</td>"
                        data=data "<td>" iView "</td></tr>"
                        print data
                #}
        }
}
#-- end of awk script ---------------------------------------------------------
:end
[ Last edited by willsort on 2006-5-3 at 23:45 ]
作者: 无奈何     时间: 2006-5-5 23:35
To willsort
对你附件中提供的脚本作了一下修改,分别是 5、6、13、16、18 行,添加37-41行。
第5行:concmd 能自动识别编码,不如让其自动识别。
第6行:%0 在我这里提示找不到文件。我比较欣赏这段 awk 代码。
第13行:含有 viewpro.php 的字符在一个片断里有两行,不过 awk 会就近匹配的,改动不改动效果一样。
第16行:原代码标题部分含有 “<” 字符的帖子有问题,如:tid=5026、tid=15269的帖子。
第18行:同 13 行。
添加37-41行:如果转成文本的话可以替换一些特殊网页字符,做成网页的话就无所谓了。


另:
我只有这个版块的操作权限,所以无法移动其它版面的帖子。
我正在整理一份 FAQ ,发觉非常艰巨,许多问题没有现成的解答,又缺乏相关联的知识...对于问题分类的话不知有什么建议?不知兄是否有收集的问题列表。

  Quote:

  1. :: cv.bat - Convert search pages to batch move pages of cn-dos forum
  2. :: 无奈何 - Mod V4: Will Sort - 2006-05-03 - CMD@WinXP
  3. :: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
  4. @echo off
  5. concmd /o:gbk ..\pages\%1*.htm? *.txt
  6. gawk "/^#-- start/{x=1;next};/^#-- end/{x=0};x" "%~f0" | gawk -f - %1*.txt? > out.txt
  7. copy /b ..\movehead.tmp+out.txt+..\movetail.tmp _bm.html
  8. copy _bm.html ..\pages\%1_bm.html
  9. goto end

  10. #awk srcipt: convert cn-dos forum serach page to plain text form
  11. #-- start of awk script -------------------------------------------------------
  12. /viewthread.php\?tid=/,/viewpro.php\?uid=/{
  13.         if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
  14.                 sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
  15.                 sTitle=gensub(/.*\?tid=[0-9]*\&fpage=[^>]*>(.*)/,"\\1","g",gensub(/<\/a>.*/,"","g"))
  16.         }
  17.         if ($0~/viewpro.php\?uid=/){
  18.                 sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
  19.                 getline
  20.                 sDate=gensub(/[ \t]*<[^>]*>/,"","g")
  21.                 getline
  22.                 iReply=gensub(/[ \t]*<[^>]*>/,"","g")+0
  23.                 getline
  24.                 iView=gensub(/[ \t]*<[^>]*>/,"","g")+0
  25.                 iNo2=iNo2+1
  26.                 #if (iReply>=5 || iView>=50) {
  27.                         iNo1=iNo1+1
  28.                         data="<tr><td><input type=\"checkbox\" name=\"moderate[]\" "
  29.                         data=data "value=\"" sTid "\" checked></td>"
  30.                         data=data "<td><a href=viewthread.php?tid=\"" sTid "\">"
  31.                         data=data "[" iNo1 "-" int((iNo2-1)/30)+1 ":" (iNo2-1)%30+1
  32.                         data=data "-" sTid "]" sTitle "</a></td><td>" sAuthor "</td>"
  33.                         data=data "<td>" sDate "</td><td>" iReply "</td>"
  34.                         data=data "<td>" iView "</td></tr>"

  35.                         #data=gensub(/&lt;/,"<","g",data)
  36.                         #data=gensub(/&gt;/,">","g",data)
  37.                         #data=gensub(/&amp;/,"&","g",data)
  38.                         #data=gensub(/&quot;/,"\"","g",data)
  39.                         #data=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",data)

  40.                         print data
  41.                 #}
  42.         }
  43. }
  44. #-- end of awk script ---------------------------------------------------------
  45. :end

[ Last edited by 无奈何 on 2006-5-5 at 23:56 ]
作者: 3742668     时间: 2006-5-5 23:49
辛苦二位了,好象就是我比较懒。
不好意思了,生来比较懒惰,又比较浮躁,所以没帮上什么忙,不过我看转了不少贴过来了,想来这第一步应该搞定了吧。
接下来的工作,有什么需要我的说一声,版块里的回帖我会尽力的,只要力所能及,决不会让网友觉得本版无人的....
作者: willsort     时间: 2006-5-7 03:54
Re 无奈何:

      批处理主题转移工作现已基本完成,主要包括各版区标题中含有“批处理”的主题、解答室内容中含有“echo”的主题,并且经过查看数和回复数的双重筛选。

      根据你的建议,修改出了第5版脚本,新的文件包从附件中下载,其主要更新如下:

      1、支持命令行参数中控制论坛版区号fid和页号page;
      2、因为gawk支持utf-8,同时concmd不支持带[]的文件名,因此取消concmd的依赖,并随之修改了head/tail文件;
      3、增加了生成纯文本表单的脚本代码;
      4、修正了含有标题中含有<>时的错误;
      
      目前,仍有以下问题需要解决:

      1、自动判断主题列表或搜索页面中论坛fid并替换管理页面中对应fid,进一步的可以将混杂主题按fid进行分拣,第7行的脚本简单却不够简洁;
      2、按照主题发表或回复日期的区间进行选取,但未在awk中找到日期比较的相关函数或代码;
      3、为了兼容性的考虑,舍弃了CMD增强特性,%0的问题在使用全名调用时可以解决,或者使用if判断并设置变量%me%也可;

      FAQ,我曾经做过一些简单的整理,但效果很不理想,最终放弃了,因为我始终无法找到严谨性和易读性之间的平衡。不过我们有很多经典范例可以参考,比如Timo Salmi 的 TSBAT 和 TSCMD 系列,它的主要来源是usenet新闻组, TSCMD 至今仍在不断更新。即使我们只是将它翻译出来,其意义也相当重大,只是我目前的英语水平和工作时间都很有限,无法给你提供更有力的帮助了。
CODE:  [Copy to clipboard]
:: cvbm.bat - Convert html/php pages to batch move pages of cn-dos forum
:: 无奈何 - Mod V5: Will Sort & 无奈何 - 2006-05-07 - CMD@WinXP
:: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
@echo off
if not exist pages\cv%1_%2*.* goto end
gawk "/^#<-/{x=1;next};/^#>-/{x=0};x" %0 | gawk -f - pages\cv%1_%2*.* >out.tmp
gawk "{if($0~/fid=/){print gensub(/fid=[0-9]*/,\"fid=%1\",\"g\")}else{print $0}}" cvbmhead.utf>cvbmhead.tmp
copy /b cvbmhead.tmp+out.tmp+cvbmtail.utf cvbm.html>nul
copy cvbm.html pages\bm%1%2.html>nul
for %%f in (*.tmp) do del %%f
goto end

#awk srcipt: convert cn-dos forum serach page to plain text form
#<-- start of awk script ------------------------------------------------------
/viewthread/,/viewpro/{
    if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
        sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
        data=gensub(/<\/a>.*/,"","g")
        sTitle=gensub(/.*\?tid=[^>]*>(.*)/,"\\1","g",data)
        #getline
        #sFid=gensub(/.*\?fid=([0-9]*).*/,"\\1","g")
    }
    if ($0~/viewpro/){
        sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
        getline
        sDate=gensub(/[ \t]*<[^>]*>/,"","g")
        getline
        iReply=gensub(/[ \t]*<[^>]*>/,"","g")+0
        getline
        iView=gensub(/[ \t]*<[^>]*>/,"","g")+0
        iNo2=iNo2+1
        if (iReply>=5 && iView>=100) {
            iNo1=iNo1+1
            data="<tr><td><input type=\"checkbox\" name=\"moderate[]\" "
            data=data "value=\"" sTid "\" checked></td>"
            data=data "<td><a href=http://www.cn-dos.net/forum/"
            data=data "viewthread.php?tid=" sTid ">{" iNo1 ","
            data=data int((iNo2-1)/30)+1 "-" (iNo2-1)%30+1 ","
            data=data sTid "}" sTitle "</a></td><td>" sAuthor
            data=data "</td><td>" iReply "</td><td>" iView
            data=data "</td><td>" sDate "</td></tr>"

            #data=gensub(/&lt;/,"<","g",data)
            #data=gensub(/&gt;/,">","g",data)
            #data=gensub(/&amp;/,"&","g",data)
            #data=gensub(/&quot;/,"\"","g",data)
            #data=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",data)

            print data
        }
        #printf ("%04d %05d %05d %s %s %s\n",iReply,iView,iTid,sDate, sTitle,sAuthor)
    }
}
#>- end of awk script ---------------------------------------------------------
:end
附件:http://cndos.l009.com/filedown/files/CVBM5.rar

[ Last edited by willsort on 2006-5-7 at 04:30 ]
作者: 无奈何     时间: 2006-5-8 00:46
To willsort

gawk 有时间函数。
例:mktime("2006 5 8 0 0 0") 返回距 1970-01-01 00:00:00 的间隔。
      strftime("%Y%m%d",systime()-30*24*3600) 返回当前日期前30天日期。

可参考链接:http://www.delorie.com/gnu/docs/gawk/gawk_138.html
=============
增补:
关于FAQ的整理,我无法进行下去了。基础知识匮乏,语言表达太差,不可能弄出像样的东西。还是省下点时间干点别的吧。看了willsort 兄的推荐,发觉中外之间差距太大了。我的英语的水平相当的烂,绝大部分猜意。
根据你的建议,修改了一下脚本,改动不少几乎重写,见下一贴。
=============

[ Last edited by 无奈何 on 2006-5-14 at 23:13 ]
作者: 无奈何     时间: 2006-5-14 23:43
终于会用 getopt 扩展函数了,现在可以直接从命令行比较灵活的接收参数了。
        主要变动如下:
        1、将两个模板文件改为一个。
        2、可以指定、反选指定版块主题帖子。
        3、可以替换页面中对应fid了,并能显示对应版块移动帖子数。
        4、比较灵活的选定发帖日期的区间,和回帖数及查看数。
        5、可以输出为文本或网页了。
        由于没有写过太长的东西,所以可能有些乱。我花的时间不少,但代码很粗糙,也没来得及加注释,请 willsort 兄帮忙看看有没有问题。我会整理一下再帖。
CODE:  [Copy to clipboard]
:: cvbm.bat - Convert html/php pages to batch move pages of cn-dos forum
:: Mod V6.1: Will Sort & 无奈何 - 2006-05-16 - CMD@WinXP
:: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
@echo off
if not exist cvbm.html goto end
gawk "/^#<-/{x=1;next};/^#>-/{x=0};x" %0 | gawk -f - -- %*
goto end

#awk srcipt: convert cn-dos forum serach page to plain text form
#<-- start of awk script ------------------------------------------------------
#获取命令行参数函数,取自 Gawk 帮助。
function getopt(argc, argv, options,     thisopt, i){
        if (length(options) == 0)        # no options given
                return -1

        if (argv[Optind] == "--") {  # all done
                Optind++
                _opti = 0
                return -1
        } else if (argv[Optind] !~ /^-[^: \t\n\f\r\v\b]/) {
                _opti = 0
                return -1
        }
        if (_opti == 0)
                _opti = 2
        thisopt = substr(argv[Optind], _opti, 1)
        Optopt = thisopt
        i = index(options, thisopt)
        if (i == 0) {
                if (Opterr)
                        printf("参数格式不正确 -- \"%c\"。\n",
                                                                  thisopt) > "/dev/stderr"
                if (_opti >= length(argv[Optind])) {
                        Optind++
                        _opti = 0
                } else
                        _opti++
                return "?"
        }
        if (substr(options, i + 1, 1) == ":") {
                # get option argument
                if (length(substr(argv[Optind], _opti + 1)) > 0)
                        Optarg = substr(argv[Optind], _opti + 1)
                else
                        Optarg = argv[++Optind]
                _opti = 0
        } else
                Optarg = ""
        if (_opti == 0 || _opti >= length(argv[Optind])) {
                Optind++
                _opti = 0
        } else
                _opti++
        return thisopt
}
function xdate(     dat){
        x=gensub (/(.+)[-\.](.+)[-\.](.+)/,"\\1 \\2 \\3 0 0 0","g",dat)
        return mktime(x)
}
#将三个数字比较,完成是否符合所限区间的判断。
function compare(A, B, C){
        if ((C==-1)||(C==0)){
                if (A>=B)
                        return 1
                }
        else if ((B==-1)||(B==0)){
                if (A<=C)
                return 2
        }
        else if ((A<=C)&&(A>=B))
                return 3
        return -1
}
function usage(     e){
        e = "Usage: cvbm.bat [-i [!]FidNumber] [-d YYYY-MM-DD[:YYYY-MM-DD] | :YYYY-MM-DD]\n"
        e = e "\t[-r Reply[:Reply] | :Reply] [-v View[:View] | :View]\n"
        e = e "\t[-o {[a]t | h}] file...\n\n"
        e = e "\t-i\t限定论坛 Fid 为(或不为) IdNumber 的主题。\n"
        e = e "\t-d\t限定主题发表日期符合区间的主题。\n"
        e = e "\t\tYYYY-MM-DD 日期格式为 年-月-日。\n"
        e = e "\t\t“:” 可指定日期区间为闭区间或半开区间,省略时为后半开区间。\n"
        e = e "\t-r\t限定回复贴数符合区间的主题,“:” 同 -d 选项。\n"
        e = e "\t-v\t限定浏览贴数符合区间的主题,“:” 同 -d 选项。\n"
        e = e "\t-o\t输出到文件。-o 为修饰性参数,可省略为其后的 -t 或 -h 参数。\n"
        e = e "\t\tt 选项输出为文本文件,加参数 a 可追加到文本末尾。\n"
        e = e "\t\th 选项输出为网页文件。-oat -oh 可简写为 -at -h 。\n"
        e = e "\t-?\t显示简短帮助。\n\n"
        e = e "Exatmples:\n\tcvbm.bat -i 9 -d 2004.12.31 -r 5:10 -v 100 *.php\n"
        e = e "\tcvbm.bat -i !9 -d :2005-12-31 -r 10 -v 200:500 *.html\n"
        e = e "\tcvbm.bat -d 2004-12-31:2005.12.31 -r :1 -oh out.html *.html\n"
        e = e "\tcvbm.bat -oat out.txt *.html\n"
        print e > "/dev/stderr"
        exit 1
}
BEGIN {
        Opterr = 1        # default is to diagnose
        Optind = 1        # skip ARGV[0]
        if (ARGV[1]=="")
                usage()
        if (ARGV[1]=="-?")
                usage()
#设定选项字符。字母后不跟随 : 字符的,只获得参数,不获取其后参数值。
        while ((c = getopt(ARGC, ARGV, "i:d:r:v:oah:t:")) != -1) {
                if (c=="i") {
                        fFid=1
                        Fid=Optarg        #获取论坛版块的 Fid 值。
                        if ((substr(Fid,1,1))=="!"){
                                xFid=1
                                sub("!","",Fid)
                        }
                }
                else if (c=="d") {
                        Date=Optarg        #获取日期区间,起止值存于 d 数组。
                        split(Date,d,":")
                        date1=xdate(d[1])
                        date2=xdate(d[2])
                }
                else if (c=="r"){
                        Reply=Optarg
                        split(Reply,r,":")
                        r[1]+=0
                        r[2]+=0
                }
                else if (c=="v"){
                        View=Optarg
                        split(View,v,":")
                        v[1]+=0
                        v[2]+=0
                }
                else if (c=="o")
                        fOut=1        #此值无意义,o 选项只起修饰作用。
                else if (c=="a")
                        fAdd=1
                else if (c=="h"){
                                fHtml=1
                                filename=Optarg
                }
                else if (c=="t"){
                                fTxt=1
                                filename=Optarg
                }
                else
                        usage()
        }
        #删除已识别参数。
        for (i=1;i<Optind;i++)
                delete ARGV[i]
        #读取模板文件。
        while ((getline<"cvbm.html") >0){
                if (!($0~/@sTitle/)){
                        if ($0~/^[ \t]*<!--.*-->$/){
                                #读取版块 Fid 与版块名的对应表。
                                Fidlist=gensub(/^[ \t]*<!--(.*)-->$/,"\\1","g")
                                split(Fidlist,Fid_tmp,"\t")
                                for (i in Fid_tmp){
                                        if (i~/^[0-9]+$/)
                                                Fid_array[Fid_tmp[i]]=Fid_tmp[i+1]
                                        delete Fid_tmp[i]
                                        }
                                continue
                                }
                        if (!k)
                                cvbmhead=cvbmhead "\n" $0
                        else
                                cvbmtail=cvbmtail "\n" $0
                } else {
                        data_tmp=$0
                        k=1        #分割模板为头尾两部分的标记变量。
                }
        }
        if (fHtml)
                print cvbmhead > filename
        else if (!fTxt)
                print cvbmhead
}

/viewthread/,/viewpro/{
        if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
                sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
                sTitle=gensub(/.*\?tid=[^>]*>(.*)/,"\\1","g",gensub(/<\/a>.*/,"","g"))
                getline
                sFid=gensub(/.*\?fid=([0-9]*).*/,"\\1","g")
                pFid = 1        #默认处理所有版块。
                if (fFid) {
                        if (Fid!=sFid)
                                pFid=0
                        if (xFid)
                                pFid=(pFid+1)%2
                }
        }
        if ($0~/viewpro/ && (pFid)) {
                sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                sDate=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                iReply=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                iView=gensub(/[ \t]*<[^>]*>/,"","g")
                date_=xdate(sDate)
                #判断日期回复数及浏览数是否符合条件。
                if ((compare(date_+0, date1+0, date2+0)>0) \
                        && (compare(iReply+0, r[1]+0, r[2]+0)>0) \
                        && (compare(iView+0, v[1]+0, v[2]+0)>0)) {
                                data=gensub("@sTid",sTid,"g",data_tmp)
                                data=gensub("@sTitle",sTitle,"g",data)
                                data=gensub("@sAuthor",sAuthor,"g",data)
                                data=gensub("@sDate",sDate,"g",data)
                                data=gensub("@iReply",iReply,"g",data)
                                data=gensub("@iView",iView,"g",data)
                                if (fHtml)
                                        print data > filename
                                else if (!fTxt)
                                        print data
                                if (fTxt){
                                        sTitle=gensub(/&lt;/,"<","g",sTitle)
                                        sTitle=gensub(/&gt;/,">","g",sTitle)
                                        sTitle=gensub(/&amp;/,"&","g",sTitle)
                                        sTitle=gensub(/&quot;/,"\"","g",sTitle)
                                        sTitle=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",sTitle)
                                        if (fAdd)
                                                print sTitle "\t" sAuthor "\t" sTid "\t" sDate "\t" iReply "\t" iView >> filename
                                        else
                                                print sTitle "\t" sAuthor "\t" sTid "\t" sDate "\t" iReply "\t" iView > filename
                                }
                                id[sFid]++        #统计各版块输出帖子数
                }
        }
}
END{
        #修改各版块统计信息。
        for (i in id){
                sub("@sFid","&" id[i] "  ----  " Fid_array[i] "<br>",cvbmtail)
        }
        sub("@sFid","",cvbmtail)
        gsub("@sFid","\\&",cvbmtail)
        if (fHtml)
                print cvbmtail > filename
        else if (!fTxt)
                print cvbmtail
}

#>- end of awk script ---------------------------------------------------------
:end
[ Last edited by 无奈何 on 2006-5-16 at 21:45 ]
附件 1: cvbm_v6.1.zip (2006-5-16 21:08, 10.56 K, 下载附件所需积分 1 点 ,下载次数: 2)

作者: willsort     时间: 2006-5-15 02:36
Re 无奈何:

      脚本中未将gawk的输出重定向而直接输出到cmd,修改后使用 *.php 参数运行出现错误[1],已输出结果中只包含第一条记录。不知是否是GAWK3.1.3的问题?

      不过说实话,未想到所有的扩展兄都是在awk脚本中实现的。在我原本的计划中,参数的传递是通过批处理与awk脚本相互交互来实现的,通过批处理接受和分析参数,并用gawk命令行脚本替换awk脚本正文中的限制域变量标记。这样也许会简单一些。

  Quote:
gawk: -:176: (FILENAME=cv9_6.php FNR=105) fatal error: internal error

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.


作者: 无奈何     时间: 2006-5-16 21:30
To  willsort
        小更新了一下,主要是修正了一处盲目精简产生的错误,增加了输出到文件的参数。我不知道你修改了哪里,现在用 Gawk 3.10、3.13、3.15 都能正确执行。Gawk 数字和字符的模糊使用,让我费了好大力气才找到错误点。
        已知的问题是没有加入参数值有效性的判断,可能得到非预想的结果。兄帮忙看看还有其它问题和改进的地方没有。现在基本上是可以满足简单要求的实用版本了。
作者: willsort     时间: 2006-5-17 01:20
Re 无奈何:

      进行了一些简单的修改:

      1、usage()中三处笔误;
      2、compare()改写为MatchThread();
      3、html输出增设序号栏,便于比较和定位;
      4、主题信息不再向控制台输出(未解决Unicode的显示问题);
      5、各版统计信息改向输出到控制台;
      6、一些变量名的修改;

      尚待解决的问题:

      1、版区id与版块名列表改从<option>标签中获取,省略相关的注释;
      2、命令行参数加入目标版区的设置;
      3、主题按版区id进行分拣,每个版区一个输出结果;
      4、生成的txt文件使用“记事本”可以识别其Unicode码;
CODE:  [Copy to clipboard]
:: cvbm.bat - Convert html/php pages to batch move pages of cn-dos forum
:: Mod V6.2: Will Sort & 无奈何 - 2006-05-17 - CMD@WinXP
:: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
@echo off
if not exist cvbm.html goto end
gawk "/^#<-/{x=1;next};/^#>-/{x=0};x" %0 | gawk -f - -- %*
goto end

#awk srcipt: convert cn-dos forum serach page to plain text form
#<-- start of awk script ------------------------------------------------------
#获取命令行参数函数,取自 Gawk 帮助。
function getopt(argc, argv, options,     thisopt, i){
    if (length(options) == 0)   # no options given
        return -1
    if (argv[Optind] == "--") {  # all done
        Optind++
        _opti = 0
        return -1
    } else if (argv[Optind] !~ /^-[^: \t\n\f\r\v\b]/) {
        _opti = 0
        return -1
    }
    if (_opti == 0)
        _opti = 2
    thisopt = substr(argv[Optind], _opti, 1)
    Optopt = thisopt
    i = index(options, thisopt)
    if (i == 0) {
        if (Opterr)
            printf("参数格式不正确 -- \"%c\"。\n", thisopt) > "/dev/stderr"
        if (_opti >= length(argv[Optind])) {
            Optind++
            _opti = 0
        } else
            _opti++
        return "?"
    }
    if (substr(options, i + 1, 1) == ":") {
        # get option argument
        if (length(substr(argv[Optind], _opti + 1)) > 0)
            Optarg = substr(argv[Optind], _opti + 1)
        else
            Optarg = argv[++Optind]
        _opti = 0
    } else
        Optarg = ""
    if (_opti == 0 || _opti >= length(argv[Optind])) {
        Optind++
        _opti = 0
    } else
        _opti++
    return thisopt
}
function DateToNum(     dat){
    x=gensub (/(.+)[-\.](.+)[-\.](.+)/,"\\1 \\2 \\3 0 0 0","g",dat)
    return mktime(x)
}
#判断当前主题的发表日期、回复数和查看数是否符合设定范围
function MatchThread(pdate, reply, view){
    if (pdate<0 || reply<0 || view<0)
        return 0
    if (vDate[1]>0 && pdate<vDate[1] || vDate[2]>0 && pdate>vDate[2])
        return 0
    if (vReply[1]>0 && reply<vReply[1] || vReply[2]>0 && reply>vReply[2])
        return 0
    if (vView[1]>0 && view<vView[1] || vView[2]>0 && view>vView[2])
        return 0
    return 1
}
function usage(     e){
    e = "Usage: cvbm.bat [-i [!]FidNumber] [-d YYYY-MM-DD[:YYYY-MM-DD] | :YYYY-MM-DD]\n"
    e = e "\t[-r Reply[:Reply] | :Reply] [-v View[:View] | :View]\n"
    e = e "\t[-o {[a]t | h}] file...\n\n"
    e = e "\t-i\t限定论坛 Fid 为(或不为) IdNumber 的主题。\n"
    e = e "\t-d\t限定主题发表日期符合区间的主题。\n"
    e = e "\t\tYYYY-MM-DD 日期格式为 年-月-日。\n"
    e = e "\t\t“:” 可指定日期区间为闭区间或半开区间,省略时为后半开区间。\n"
    e = e "\t-r\t限定回复帖数符合区间的主题,“:” 同 -d 选项。\n"
    e = e "\t-v\t限定浏览帖数符合区间的主题,“:” 同 -d 选项。\n"
    e = e "\t-o\t输出到文件。-o 为修饰性参数,可省略为其后的 -t 或 -h 参数。\n"
    e = e "\t\tt 选项输出为文本文件,加参数 a 可追加到文本末尾。\n"
    e = e "\t\th 选项输出为网页文件。-oat -oh 可简写为 -at -h 。\n"
    e = e "\t-?\t显示简短帮助。\n\n"
    e = e "Examples:\n\tcvbm.bat -i 9 -d 2004.12.31 -r 5:10 -v 100 *.php\n"
    e = e "\tcvbm.bat -i !9 -d :2005-12-31 -r 10 -v 200:500 *.html\n"
    e = e "\tcvbm.bat -d 2004-12-31:2005.12.31 -r :1 -oh out.html *.html\n"
    e = e "\tcvbm.bat -oat out.txt *.html\n"
    print e > "/dev/stderr"
    exit 1
}
BEGIN {
    Opterr = 1  # default is to diagnose
    Optind = 1  # skip ARGV[0]
    if (ARGV[1]=="")
        usage()
    if (ARGV[1]=="-?")
        usage()
#设定选项字符。字母后不跟随 : 字符的,只获得参数,不获取其后参数值。
    while ((c = getopt(ARGC, ARGV, "i:d:r:v:oah:t:")) != -1) {
        if (c=="i") {
            fFid=1
            Fid=Optarg  #获取论坛版块的 Fid 值。
            if ((substr(Fid,1,1))=="!"){
                xFid=1
                sub("!","",Fid)
            }
        }
        else if (c=="d") {
            Date=Optarg #获取日期区间,起止值存于 _vd 数组。
            split(Date,_vd,":")
            vDate[1]=DateToNum(_vd[1])
            vDate[2]=DateToNum(_vd[2])
        }
        else if (c=="r"){
            Reply=Optarg
            split(Reply,vReply,":")
            vReply[1]+=0
            vReply[2]+=0
        }
        else if (c=="v"){
            View=Optarg
            split(View,vView,":")
            vView[1]+=0
            vView[2]+=0
        }
        else if (c=="o")
            fOut=1  #此值无意义,o 选项只起修饰作用。
        else if (c=="a")
            fAdd=1
        else if (c=="h"){
                fHtml=1
                filename=Optarg
        }
        else if (c=="t"){
                fTxt=1
                filename=Optarg
        }
        else
            usage()
    }
    #删除已识别参数。
    for (i=1;i<Optind;i++)
        delete ARGV[i]
    #读取模板文件。
    while ((getline<"cvbm.html") >0){
        if (!($0~/@sTitle/)){
            if ($0~/^[ \t]*<!--.*-->$/){
                #读取版块 Fid 与版块名的对应表。
                Fidlist=gensub(/^[ \t]*<!--(.*)-->$/,"\\1","g")
                split(Fidlist,Fid_tmp,"\t")
                for (i in Fid_tmp){
                    if (i~/^[0-9]+$/)
                        Fid_array[Fid_tmp[i]]=Fid_tmp[i+1]
                    delete Fid_tmp[i]
                }
                continue
            }
            if (!k)
                cvbmhead=cvbmhead "\n" $0
            else
                cvbmtail=cvbmtail "\n" $0
        } else {
            data_tmp=$0
            k=1 #分割模板为头尾两部分的标记变量。
        }
    }
    if (fHtml)
        print cvbmhead > filename
}

/viewthread/,/viewpro/{
    if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
        sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
        sTitle=gensub(/.*\?tid=[^>]*>(.*)/,"\\1","g",gensub(/<\/a>.*/,"","g"))
        getline
        sFid=gensub(/.*\?fid=([0-9]*).*/,"\\1","g")
        pFid = 1    #默认处理所有版块。
        if (fFid) {
            if (Fid!=sFid)
                pFid=0
            if (xFid)
                pFid=(pFid+1)%2
        }
    }
    if ($0~/viewpro/ && (pFid)) {
        sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
        getline
        sDate=gensub(/[ \t]*<[^>]*>/,"","g")
        getline
        iReply=gensub(/[ \t]*<[^>]*>/,"","g")+0
        getline
        iView=gensub(/[ \t]*<[^>]*>/,"","g")+0
        iDate=DateToNum(sDate)
        iNo1=iNo1+1
        #判断发表日期、回复数及浏览数是否符合条件。
        if (MatchThread(iDate, iReply, iView)) {
            iNo2=iNo2+1
            sNo=iNo2 "(" sFid "-" int((iNo1-1)/30)+1 "-" (iNo1-1)%30+1 ")"
            if (fHtml) {
                data=gensub("@sTid",sTid,"g",data_tmp)
                data=gensub("@sNo",sNo,"g",data_tmp)
                data=gensub("@sTitle",sTitle,"g",data)
                data=gensub("@sAuthor",sAuthor,"g",data)
                data=gensub("@sDate",sDate,"g",data)
                data=gensub("@iReply",iReply,"g",data)
                data=gensub("@iView",iView,"g",data)
                print data > filename
            }
            if (fTxt) {
                sTitle=gensub(/&lt;/,"<","g",sTitle)
                sTitle=gensub(/&gt;/,">","g",sTitle)
                sTitle=gensub(/&amp;/,"&","g",sTitle)
                sTitle=gensub(/&quot;/,"\"","g",sTitle)
                sTitle=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",sTitle)
                data=sTitle "\t" sAuthor "\t" sTid "\t" sDate "\t" iReply "\t" iView
                if (fAdd)
                    print data>>filename
                else
                    print data>filename
            }
            iTotal[sFid]++  #统计各版块输出帖子数
        }
    }
}
END{
    #打印各版块统计信息。
    for (i in iTotal){
        printf("%-3d%-60s%5d\n", i, Fid_array[i], iTotal[i])
    }
    if (fHtml)
        print cvbmtail > filename
}
#>- end of awk script ---------------------------------------------------------
:end
[ Last edited by willsort on 2006-5-17 at 01:23 ]
作者: willsort     时间: 2006-5-17 20:49
To All:

      做出将TSCMD和TSBAT原文转贴的尝试,但我的感觉效果不佳。

      语言限制使它的受众范围变窄,而大体积导致浏览速度变慢加剧了这个问题。

      也许将在首帖中将之作为附件提供下载,以后再逐篇翻译后回复贴出是个好办法。可惜自己英文基础薄弱,仅能勉强自我理解,想要准确传达却是做不到了。不知各位版主和脚本高手中是否有人愿意承担此项任务?
作者: 无奈何     时间: 2006-5-21 22:52
TO willsort
        由于域名问题连续几日不能访问论坛,终于又追过来了。
        继续修改了一下脚本,解决了兄提出的问题。借鉴网上流传的PHP代码,写了个转码函数,终于彻底解决了 UTF-8 的显示问题,感谢整理换码表的不知名的作者。
        相对于上一版改动如下:

        * 版区id与版块名列表改从<option>标签中获取。
        + 加入命令行参数 “-m” 可设置目标版区。
        + 加入命令行参数 “-s” 可按主题版区id进行分拣,每个版区一个输出结果。
        * 生成的txt文件使用“记事本”可以直接识别其Unicode码。
        * 彻底解决了 UTF-8 的显示问题。

        尚存在的问题:
        1、为使编辑软件可识别文本为 UTF-8 编码,加入了 BOM 信息,在追加模式会产生多余的 BOM 字符,不过显示倒是正常。
        2、帮助信息实在太烂,总感觉说不明白,更别谈雅达信了。请兄帮忙润色一下。
        还想加入主题作者过滤选项,不知有无用处。还有修改的地方请继续提出来。
CODE:  [Copy to clipboard]
:: cvbm.bat - Convert html/php pages to batch move pages of cn-dos forum
:: Mod V6.3: Will Sort & 无奈何 - 2006-05-16 - CMD@WinXP
:: Link: http://www.cn-dos.net/forum/viewthread.php?tid=20332
@echo off
if not exist cvbm.html goto end
if not exist gb2utf8.txt goto end
gawk "/^#<-/{x=1;next};/^#>-/{x=0};x" %0 | gawk -f - -- %*
goto end

#awk srcipt: convert cn-dos forum serach page to plain text form
#<-- start of awk script ------------------------------------------------------
#获取命令行参数函数,取自 Gawk 帮助。
function getopt(argc, argv, options,     thisopt, i){
        if (length(options) == 0)   # no options given
                return -1
        if (argv[Optind] == "--") {  # all done
                Optind++
                _opti = 0
                return -1
        } else if (argv[Optind] !~ /^-[^: \t\n\f\r\v\b]/) {
                _opti = 0
                return -1
        }
        if (_opti == 0)
                _opti = 2
        thisopt = substr(argv[Optind], _opti, 1)
        Optopt = thisopt
        i = index(options, thisopt)
        if (i == 0) {
                if (Opterr)
                        printf("参数格式不正确 -- \"%c\"。\n", thisopt) > "/dev/stderr"
                if (_opti >= length(argv[Optind])) {
                        Optind++
                        _opti = 0
                } else
                        _opti++
                return "?"
        }
        if (substr(options, i + 1, 1) == ":") {
                # get option argument
                if (length(substr(argv[Optind], _opti + 1)) > 0)
                        Optarg = substr(argv[Optind], _opti + 1)
                else
                        Optarg = argv[++Optind]
                _opti = 0
        } else
                Optarg = ""
        if (_opti == 0 || _opti >= length(argv[Optind])) {
                Optind++
                _opti = 0
        } else
                _opti++
        return thisopt
}
function DateToNum(     dat){
        x=gensub (/(.+)[-\.](.+)[-\.](.+)/,"\\1 \\2 \\3 0 0 0","g",dat)
        return mktime(x)
}
#判断当前主题的发表日期、回复数和查看数是否符合设定范围
function MatchThread(pdate, reply, view){
        if (pdate<0 || reply<0 || view<0)
                return 0
        if (vDate[1]>0 && pdate<vDate[1] || vDate[2]>0 && pdate>vDate[2])
                return 0
        if (vReply[1]>0 && reply<vReply[1] || vReply[2]>0 && reply>vReply[2])
                return 0
        if (vView[1]>0 && view<vView[1] || vView[2]>0 && view>vView[2])
                return 0
        return 1
}
function utf82gb(string,     utf8reg, char, result){
        utf8reg="[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]"
        RLENGTH = 1
        while(RLENGTH != -1){
                match(string,utf8reg)
                char=substr(string,RSTART,RLENGTH)
                if (RLENGTH>1)
                        char=charset[char]
                result=result char
                string=substr(string,RSTART+RLENGTH)
        }
        return result
}
function usage(     e){
        e = "Usage: cvbm.bat [-i [!]IdNumber] [-d YYYY-MM-DD[:YYYY-MM-DD] | :YYYY-MM-DD]\n"
        e = e "\t[-r Reply[:Reply] | :Reply] [-v View[:View] | :View]\n"
        e = e "\t[-m IdNumber] [-o {[a]t outfile | [s]h outfile}] file...\n\n"
        e = e "\t-i\t限定论坛 ID 为(或非) IdNumber 的主题。\n"
        e = e "\t-d\t限定主题发表日期符合区间的主题。\n"
        e = e "\t\tYYYY-MM-DD 日期格式为 年-月-日。\n"
        e = e "\t\t“:” 可指定日期区间为闭区间或半开区间,省略时为后半开区间。\n"
        e = e "\t-r\t限定回复帖数符合区间的主题,“:” 同 -d 选项。\n"
        e = e "\t-v\t限定浏览帖数符合区间的主题,“:” 同 -d 选项。\n"
        e = e "\t-m\t设定目标版区为 IdNumber 的版块。此选项依赖 -h 参数。\n"
        e = e "\t-o\t输出到文件。-o 为修饰性参数,可省略为其后的 -t 或 -h 参数。\n"
        e = e "\t\tt 选项输出到文本文件,加参数 a 可追加到文本末尾。\n"
        e = e "\t\th 选项输出到网页文件,加参数 s 可按版块分类输出。\n"
        e = e "\t\t其中 -oat -osh 可简写为 -at -sh 。\n"
        e = e "\t-?\t显示简短帮助。\n\n"
        e = e "Examples:\n\tcvbm.bat -i !9 -d 2004.12.31 -v :50 *.html\n"
        e = e "\tcvbm.bat -i 9 -d :2005-12-31 -r 5 -v 200 -oat out.txt *.html\n"
        e = e "\tcvbm.bat -d 2004-12-31:2005.12.31 -r :1 -oh out.html *.html\n"
        e = e "\tcvbm.bat -osh out.html *.html\n"
        print e > "/dev/stderr"
        exit 1
}
BEGIN {
        Opterr = 1  # default is to diagnose
        Optind = 1  # skip ARGV[0]
        moveto = 23  #设定默认目标版区为批处理室。
        if (ARGV[1]=="")
                usage()
        if (ARGV[1]=="-?")
                usage()
        #设定选项字符。字母后不跟随 : 字符的,只获得参数,不获取其后参数值。
        while ((c = getopt(ARGC, ARGV, "i:d:r:v:soah:t:m:")) != -1) {
                if (c=="i") {
                        fFid=1
                        Fid=Optarg  #获取论坛版块的 Fid 值。
                        if ((substr(Fid,1,1))=="!"){
                                xFid=1
                                sub("!","",Fid)
                        }
                }
                else if (c=="d") {
                        Date=Optarg #获取日期区间,起止值存于 _vd 数组。
                        split(Date,_vd,":")
                        vDate[1]=DateToNum(_vd[1])
                        vDate[2]=DateToNum(_vd[2])
                }
                else if (c=="r"){
                        Reply=Optarg
                        split(Reply,vReply,":")
                        vReply[1]+=0
                        vReply[2]+=0
                }
                else if (c=="v"){
                        View=Optarg
                        split(View,vView,":")
                        vView[1]+=0
                        vView[2]+=0
                }
                else if (c=="o")
                        fOut=1  #此值无意义,o 选项只起修饰作用。
                else if (c=="a")
                        fAdd=1
                else if (c=="h"){
                                fHtml=1
                                filename=Optarg
                }
                else if (c=="t"){
                                fTxt=1
                                filename=Optarg
                }
                else if (c=="m"){
                                moveto=Optarg
                }
                else if (c=="s")
                        fsort=1  #设置分类模式标志。
                else
                        usage()
        }
        #删除已识别参数。
        for (i=1;i<Optind;i++)
                delete ARGV[i]
        #读取转码表。
        FS=","
        while((getline<"gb2utf8.txt") > 0)
                charset[$2]=$1
        close("gb2utf8.txt")
        #读取模板文件。
        while ((getline<"cvbm.html") > 0){
                if (!($0~/@sTitle/)){
                        if ($0~/^[ \t]*<option value=/){
                                #读取版块 Fid 与版块名的对应表。
                                Fidlist=gensub(/<\/option>/,"\t","g")
                                Fidlist=gensub(/<option value=\"([0-9]+)\">/,"\\1\t","g",Fidlist)
                                Fidlist=gensub(/<option value=[^\t]+\t/,"","g",Fidlist)
                                Fidlist=gensub(/[ \t]*<\/select><\/td>/,"","g",Fidlist)
                                Fidlist=gensub(/&ensp; |&emsp; |&nbsp; |&gt; /,"","g",Fidlist)
                                j=split(Fidlist,Fid_tmp,"\t")
                                for (i=1;i<=j;i++){
                                        if (Fid_tmp[i]~/^[0-9]+$/)
                                                Fid_array[Fid_tmp[i]]=Fid_tmp[i+1]  #将版块 Fid 与版块名存到关联数组。
                                        delete Fid_tmp[i]
                                }
                                #设定目标版区。
                                str="(.*)(<option value=\"" moveto "\">[^/]+</option>)(.*)"
                                $0=gensub(str,"\\2\\1\\2\\3",$0)
                        }
                        if (!k)
                                cvbmhead=cvbmhead "\n" $0
                        else
                                cvbmtail=cvbmtail "\n" $0
                } else {
                        data_tmp=$0
                        k=1  #分割模板为头尾两部分的标记变量。
                }
        }
        close("cvbm.html")
        if (fHtml)
                if (!fsort)
                        print cvbmhead > filename
        if (fTxt)
                printf "\xEF\xBB\xBF" >> filename  #写 BOM 信息到文本中
}

/viewthread/,/viewpro/{
        if ($0~/viewthread.php\?tid=[0-9]*\&fpage=/){
                sTid=gensub(/.*\?tid=([0-9]*).*/,"\\1","g")
                sTitle=gensub(/.*\?tid=[^>]*>(.*)/,"\\1","g",gensub(/<\/a>.*/,"","g"))
                getline
                sFid=gensub(/.*\?fid=([0-9]*).*/,"\\1","g")
                pFid = 1    #默认处理所有版块。
                if (fFid) {
                        if (Fid!=sFid)
                                pFid=0
                        if (xFid)
                                pFid=(pFid+1)%2
                }
        }
        if ($0~/viewpro/ && (pFid)) {
                sAuthor=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                sDate=gensub(/[ \t]*<[^>]*>/,"","g")
                getline
                iReply=gensub(/[ \t]*<[^>]*>/,"","g")+0
                getline
                iView=gensub(/[ \t]*<[^>]*>/,"","g")+0
                iDate=DateToNum(sDate)
                iNo1=iNo1+1
                #判断发表日期、回复数及浏览数是否符合条件。
                if (MatchThread(iDate, iReply, iView)) {
                        iNo2=iNo2+1
                        sNo=iNo2 "(" sFid "-" int((iNo1-1)/30)+1 "-" (iNo1-1)%30+1 ")"
                        if (fHtml) {
                                data=gensub("@sTid",sTid,"g",data_tmp)
                                data=gensub("@sNo",sNo,"g",data)
                                data=gensub("@sTitle",sTitle,"g",data)
                                data=gensub("@sAuthor",sAuthor,"g",data)
                                data=gensub("@sDate",sDate,"g",data)
                                data=gensub("@iReply",iReply,"g",data)
                                data=gensub("@iView",iView,"g",data)
                                if (fsort){
                                        sort_array[sFid]=sort_array[sFid] "\n" data
                                        }
                                else
                                        print data > filename
                        }
                        if (fTxt) {
                                sTitle=gensub(/&lt;/,"<","g",sTitle)
                                sTitle=gensub(/&gt;/,">","g",sTitle)
                                sTitle=gensub(/&amp;/,"&","g",sTitle)
                                sTitle=gensub(/&quot;/,"\"","g",sTitle)
                                sTitle=gensub(/&ensp;|&emsp;|&nbsp;/," ","g",sTitle)
                                data=sTitle "\t" sAuthor "\t" sTid "\t" sDate "\t" iReply "\t" iView
                                if (fAdd)
                                        print data >> filename
                                else
                                        print data > filename
                        }
                        iTotal[sFid]++  #统计各版块输出帖子数
                }
        }
}
END{
        #打印各版块统计信息。
        for (i in iTotal){
                out=out utf82gb(sprintf("%-3d%-60s%5d\n", i, Fid_array[i], iTotal[i]))
        }
        print "\n" out
        if (fsort){
                for (i in sort_array){
                        sfilename=i "_" filename
                        _cvbmhead=gensub(/\(@sFid\)/,Fid_array[i],1,cvbmhead)
                        _cvbmhead=gensub(/\(@sFid\)/,"\\&",1,_cvbmhead)
                        print _cvbmhead > sfilename
                        print sort_array[i] >> sfilename
                        print cvbmtail >> sfilename
                        close (sfilename)
                }
        }
        if (fHtml)
                if (!fsort)
                        print cvbmtail > filename
}

#>- end of awk script ---------------------------------------------------------
:end
附件 1: cvbm_v6.3.zip (2006-5-21 22:52, 44.94 K, 下载附件所需积分 1 点 ,下载次数: 6)

作者: scriptor     时间: 2007-1-4 02:21
原来这里有好东西啊

学习了
作者: hxuan999     时间: 2007-1-18 06:22
我好不容易才到300分呀.呵呵,各位版主好像很久没来了.
作者: qasa     时间: 2007-1-27 21:28
我泡在这里的时候个已经人去楼空,唉,人呢?
作者: electronixtar     时间: 2007-1-27 21:43
人就是这么流传下来的。论坛已经过了很多代人啦
作者: 无奈何     时间: 2007-1-29 00:49
willsort 兄交给的后三条任务都没有完成,希望此次制作 论坛批处理精华 时能一并完成,我也加紧制作下一版的制作。

空楼悠悠,曾经的讨论仿佛就发生昨天。




欢迎光临 中国DOS联盟论坛 (http://cndos.fam.cx/forum/) Powered by Discuz! 2.5