[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
批处理的效率虽然是比不上其它的XX,但是,也因为批处理的特点,往往是可以取巧的!!

下面的代码,实现词拆分查表功能,可以在一秒内完成:
注意:dictionary.txt 词库,需以较长的词在前,短在后的顺序排列
  1. @echo off&setlocal enabledelayedexpansion
  2. :lp
  3. set str=
  4. echo;
  5. echo;直接回车退出测试
  6. set /p str=输入一个字符串:
  7. if "!str!" equ "" goto :eof
  8. setlocal enabledelayedexpansion
  9. set/a z=8180,x=0&for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x"
  10.     for %%b in (!y!) do if "!str:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
  11. )
  12. ::计算输入串的长度
  13. ::sap 存入同等长度的空格串
  14. set sap=
  15. (for /l %%i in (0,1,!z!) do (
  16.     set "spa= !spa!"
  17.     set/a x=z-%%i
  18.     for /l %%j in (1,1,!x!) do (
  19.         echo;!str:~%%i,%%j!
  20.         set/a y=%%i+%%j
  21.         for %%a in ("!str:~%%i,%%j!") do (
  22.             set ##%%~a=%%i-!y!-%%j !##%%~a!
  23.         )
  24.     )
  25. ))>fen.tmp
  26. ::进行排列拆分到临时文件fen.tmp,同时取各分词的长度,及在原句中的起址位置,并按一定的规则保存
  27. set var=!str!
  28. for /f "tokens=*" %%a in ('findstr /x /i /g:fen.tmp dictionary.txt') do (
  29.   for %%k in (!##%%a!) do (
  30.     if "!var:%%a=!" neq "!var!" (
  31.       for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do (
  32.         if "!var:~%%b,1!" neq " " (
  33.           echo;截取过程:[!var!]  %%a
  34.           set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c!
  35.           set $$%%b=%%a
  36.         )
  37.       )
  38.     )
  39.   )
  40. )
  41. ::搜索词库,并做已经截取过记号,同时为恢复分词在原句中的位置做准备
  42. echo;
  43. if "!var: =!" neq "" (
  44.   echo;词库中没有的:
  45.   for %%a in (!var!) do (
  46.     for %%k in (!##%%a!) do (
  47.       if "!var:%%a=!" neq "!var!" (
  48.         for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do (
  49.           if "!var:~%%b,1!" neq " " (
  50.             echo;截取过程:[!var!]  %%a
  51.             set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c!
  52.             set $$%%b=%%a
  53.           )
  54.         )
  55.       )
  56.     )
  57.   )
  58. ) else (echo;所有字符均可在词库中到)
  59. ::对在词库中找不到的分词,也进行同样的处理
  60. echo;
  61. set dest=
  62. for /l %%a in (0,1,!z!) do set dest=!dest! !$$%%a!
  63. echo;最终拆分:!dest!
  64. endlocal&goto :lp
复制代码

[ 本帖最后由 netbenton 于 2010-9-15 03:32 编辑 ]

TOP

8楼的代码,因为findstr 的一些特性,存在一些bug,修改如下:

一、词库搜索代码:
    findstr /x /g:fen.tmp /f:dics.txt

二、把词库按字数分别存放,并且文件名上可见词的字数。如:
[email=dict@1.txt]dict@1.txt[/email]
1人
1们
...

[email=dict@2.txt]dict@2.txt[/email]
2人民
2后门
...

......

些种办法把词分出来后,可方便词库的维护。
以下代码可把楼主提供的词库转换成按字数分文档存放。
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (0,1,10) do del dict@%%a.txt /q
  3. echo;%time%
  4. for /f "tokens=*" %%a in (dic16.txt) do (
  5.    set str=%%a
  6.    if "!str:~9!" equ "" (
  7.       set str=0123456789%%a
  8.       set n=!str:~-10,1!
  9.       echo;!n!%%a>>dict@!n!.txt
  10.    ) else (
  11.       echo;!n!%%a>>dict@10.txt
  12.    )
  13. )
  14. (for /f %%a in (dictionar@1.txt) do (echo;1%%a))>dict@1.txt
  15. dir /o-n /b dict@*>dics.txt
  16. echo;%time%
  17. pause
复制代码
三、dics.txt  存放各分词库的文件名,以字数长的分词库在前,短在后。
    dics.txt内容:
[email=dict@10.txt]dict@10.txt[/email]
[email=dict@9.txt]dict@9.txt[/email]
[email=dict@8.txt]dict@8.txt[/email]
[email=dict@7.txt]dict@7.txt[/email]
[email=dict@6.txt]dict@6.txt[/email]
[email=dict@5.txt]dict@5.txt[/email]
[email=dict@4.txt]dict@4.txt[/email]
[email=dict@3.txt]dict@3.txt[/email]
[email=dict@2.txt]dict@2.txt[/email]
[email=dict@1.txt]dict@1.txt[/email]

四、分词代码修改后,不再有搜索漏网的bug。并且对速度影响不大,20个字数长度的句子,拆分用时在一秒内。
  1. @echo off&setlocal enabledelayedexpansion
  2. :lp
  3. set str=
  4. echo;
  5. echo;直接回车退出测试
  6. set /p str=输入一个字符串:
  7. set ti=%time%
  8. if "!str!" equ "" goto :eof
  9. setlocal enabledelayedexpansion
  10. set/a z=8180,x=0&for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x"
  11.     for %%b in (!y!) do if "!str:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
  12. )
  13. ::计算输入串的长度
  14. ::sap 存入同等长度的空格串
  15. set lens=1 2 3 4 5 6 7 8 9 10 11
  16. set/a z1=z-1
  17. set sap=
  18. (for /l %%i in (0,1,!z1!) do (
  19.     set "spa= !spa!"
  20.     set one=!str:~%%i,1! !one!
  21.     set/a x=z-%%i
  22.     for %%j in (!lens!) do (
  23.         set/a y=%%i+%%j
  24.         echo;%%j!str:~%%i,%%j!
  25.         for %%a in ("!str:~%%i,%%j!") do (
  26.             set ##%%~a=%%i-!y!-%%j !##%%~a!
  27.         )
  28.     )
  29. ))>fen.tmp
  30. ::(for /l %%a in (0,1,!z!) do for %%k in (!@%%a!) do (echo;%%k))>fen.tmp
  31. ::进行排列拆分到临时文件fen.tmp,同时取各分词的长度,及在原句中的起址位置,并按一定的规则保存
  32. ::似乎要从短到长,findstr才能完全正确查找
  33. set var=!str!
  34. echo;!vvv!
  35. for /f "tokens=2* delims=:123456789" %%1 in ('findstr /x /g:fen.tmp /f:dics.txt') do (
  36.   for %%k in (!##%%2!) do (
  37.     if "!var:%%2=!" neq "!var!" (
  38.       for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do (
  39.         if "!var:~%%b,%%d!" equ "!str:~%%b,%%d!" (
  40.           echo;截取过程:[!var!]  %%2
  41.           set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c!
  42.           set $$%%b= [%%2]
  43.         )
  44.       )
  45.     )
  46.   )
  47. )
  48. ::搜索词库,并做已经截取过记号,同时为恢复分词在原句中的位置做准备
  49. echo;
  50. if "!var: =!" neq "" (
  51.   echo;词库中没有的:
  52.   for %%a in (!var!) do (
  53.     for %%k in (!##%%a!) do (
  54.       if "!var:%%a=!" neq "!var!" (
  55.         for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do (
  56.           if "!var:~%%b,1!" neq " " (
  57.             echo;截取过程:[!var!]  %%a
  58.             set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c!
  59.             set $$%%b= %%a
  60.           )
  61.         )
  62.       )
  63.     )
  64.   )
  65. ) else (echo;所有字符均可在词库中找到)
  66. ::对在词库中找不到的分词,也进行同样的处理
  67. echo;
  68. set dest=
  69. for /l %%a in (0,1,!z!) do set dest=!dest!!$$%%a!
  70. echo;最终拆分:!dest!
  71. echo;%ti%
  72. echo;%time%
  73. endlocal&goto :lp
复制代码
五、词在库中的先后,决定了匹配的优先顺序,只要改变词在库中的顺序,即可改变折分的准确性。

我另外写了一个词库维护的代码,可以改变词在库中的顺序,增加词到词库中。

初版只支持一次修改两个词顺序。代码如下:
  1. @echo off&setlocal enabledelayedexpansion
  2. echo;  ** 调整词序/增加词组 **
  3. set /p str1=输入第一字符串:
  4. set /p str2=输入第二字符串:
  5. if "!str1!" equ "!str2!" goto :eof
  6. set str=0123456789!str1!
  7. set n1=!str:~-10,1!
  8. set str=0123456789!str2!
  9. set n2=!str:~-10,1!
  10. set str1=!n1!!str1!
  11. set str2=!n2!!str2!
  12. if "!n1!" equ "!n2!" (
  13.   findstr /x "!str1!" dict@!n1!.txt>nul
  14.   if !errorlevel! equ 1 (
  15.         set str1=%str2%
  16.         set str2=%str1%
  17.         set xchg=y
  18.      findstr /x "!str1!" dict@!n1!.txt>nul
  19.      if !errorlevel! equ 1 set xchg=n
  20.   )
  21.   if "!xchg!" neq "n" (
  22.     copy dict@!n1!.txt fen.tmp /y
  23.     (for /f %%a in (fen.tmp) do (
  24.         if "%%a" neq "!str2!" echo;%%a
  25.         if "%%a" equ "!str1!" (
  26.           echo;!str2!
  27.           if defined xchg (echo;!str1!)
  28.         )
  29.     ))>dict@!n1!.txt
  30.     echo;修改 [!str1!] 和 [!str2!] 在dict@!n1!.txt中的顺序
  31.   ) else (
  32.     echo;!str2!>>dict@!n1!.txt
  33.     echo;!str1!>>dict@!n1!.txt
  34.     echo;添加 [!str1!] 和 [!str2!] 到 dict@!n1!.txt
  35.   )
  36. ) else (
  37.   findstr /x "!str1!" dict@!n1!.txt>nul
  38.   if !errorlevel! equ 1 (
  39.     echo;!str1!>>dict@!n1!.txt
  40.     echo;添加 [!str1!] 到 dict@!n1!.txt
  41.   )
  42.   findstr /x "!str2!" dict@!n2!.txt>nul
  43.   if !errorlevel! equ 1 (
  44.      echo;!str2!>>dict@!n2!.txt
  45.      echo;添加 [!str2!] 到 dict@!n2!.txt
  46.   )
  47. )
  48. pause
复制代码
拆分句子示例:

输入一个字符串:这也是造成肇事车辆屡屡逃逸的一个主要原因

截取过程:[这也是造成肇事车辆屡屡逃逸的一个主要原因]  主要原因
截取过程:[这也是造成肇事车辆屡屡逃逸的一个           ]  屡屡
截取过程:[这也是造成肇事车辆  逃逸的一个           ]  车辆
截取过程:[这也是造成肇事    逃逸的一个           ]  逃逸
截取过程:[这也是造成肇事      的一个           ]  一个
截取过程:[这也是造成肇事      的             ]  也是
截取过程:[这  造成肇事      的             ]  造成
截取过程:[这    肇事      的             ]  肇事
截取过程:[这            的             ]  这
截取过程:[             的             ]  的
所有字符均可在词库中找到
最终拆分: [这] [也是] [造成] [肇事] [车辆] [屡屡] [逃逸] [的] [一个] [主要原因]
开始: 6:44:02.45
结束: 6:44:03.20

楼主出的测试例子结果如下(词库的一些词经过顺序调整):
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京] [天安门] [门楼] [的] [门]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京] [大学生活动中心] [门楼] [的] [门]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [生活] [在] [音乐] [里]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [生活] [很好]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [的] [学生] [生活] [在] [音乐] [里]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [的] [学生] [活在] [音乐] [里]
最终拆分: [广西] [大学生活] [很好]
最终拆分: [我] [喜欢] [吃] [鸭肉]
最终拆分: [伟] [大学生] [生活]
最终拆分: [大学生活] [动]
最终拆分: [大学生活] [好]
最终拆分: [大学生活动中心]
最终拆分: [发展] [中国家庭养猪] [事业]
最终拆分: [你说] [的] [确实在] [理]

[ 本帖最后由 netbenton 于 2010-9-17 07:31 编辑 ]

TOP

经过几次测试实验,我认为,只要对词库进行一定的“驯化”,即调整顺序、合理的增/减词汇,应该可以正确拆分所有的句子。

这种分文档存放词库方法较为灵活,可以随意调整词的优先顺序。
比如:
在最长分词库前增加一个人名库,这样就可以,以最优先权去匹配人的名字。
把dics.txt  的内容改为:
name.txt
[email]dict@10.txt[/email]
[email]dict@9.txt[/email]
[email]dict@8.txt[/email]
[email]dict@7.txt[/email]
[email]dict@6.txt[/email]
[email]dict@5.txt[/email]
[email]dict@4.txt[/email]
[email]dict@3.txt[/email]
[email]dict@2.txt[/email]
[email]dict@1.txt[/email]

然后在name.txt里面存放人名/地名等:
3刘德华
3张曼玉
4比尔盖茨
5东方不败
2香港
2桂林

这样,name.txt 中的词即得到最优先权的匹配

TOP

可以吧~~~,结果如下:

输入一个字符串:华为二十四口交换机

截取过程:[华为二十四口交换机]  二十四
截取过程:[华为   口交换机]  交换机
截取过程:[华为   口   ]  华为
截取过程:[     口   ]  口

所有字符均可在词库中找到

最终拆分: [华为] [二十四] [口] [交换机]
12:36:47.53
12:36:47.98


输入一个字符串:华为24口交换机
截取过程:[华为24口交换机]  交换机
截取过程:[华为24口   ]  华为
截取过程:[  24口   ]  口
词库中没有的:
截取过程:[  24    ]  24
最终拆分: [华为] 24 [口] [交换机]
12:45:33.93
12:45:34.34

[ 本帖最后由 netbenton 于 2010-9-17 12:46 编辑 ]

TOP

输入一个字符串:华为二十四口交不好

截取过程:[华为二十四口交不好]  二十四
截取过程:[华为   口交不好]  不好
截取过程:[华为   口交  ]  华为
截取过程:[     口交  ]  口交

所有字符均可在词库中找到

最终拆分: [华为] [二十四] [口交] [不好]
12:55:39.01
12:55:39.48

库里有那个词的,只是没有匹配到它

TOP

返回列表