Board logo

标题: [其他] 高效的纯批处理汉字转拼音 [打印本页]

作者: CrLf    时间: 2015-8-11 00:54     标题: 高效的纯批处理汉字转拼音

本帖最后由 CrLf 于 2015-8-11 20:02 编辑

因为使用简表直接比较大小,所以需要确保区域语言设置为按中文拼音排序,否则结果可能不正确:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. call :py_初始化
  4. for /f "delims=" %%a in ('help') do (
  5. set input=%%a
  6. echo;%%a
  7. call :py input newstr
  8. echo !newstr!
  9. echo;
  10. )
  11. pause
  12. exit /b
  13. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14. :py_初始化   // 需启用变量延迟后调用
  15. set 字典长度=0
  16. for %%a in (
  17. /*简表包含405个拼音,已知囊括20855个汉字范围*/
  18. 吖a 哎ai 安an 肮ang 凹ao 八ba 挀bai 扳ban 邦bang 勹bao 萡be 陂bei 奔ben 伻beng 皀bi
  19. 边bian 标biao 憋bie 汃bin 仌bing 癶bo 卜bu 攃ca 猜cai 参can 仓cang 撡cao 刂ce 岑cen 噌ceng
  20. 叉cha 犲chai 觇chan 伥chang 抄chao 车che 抻chen 阷cheng 吃chi 冲chong 抽chou 出chu 欻chua 揣chuai 川chuan
  21. 刅chuang 吹chui 杶chun 逴chuo 呲ci 匆cong 凑cou 粗cu 汆cuan 崔cui 邨cun 搓cuo 咑da 呆dai 亻dan
  22. 当dang 刀dao 恴de 揼den 灯deng 仾di 嗲dia 敁dian 刁diao 爹die 丁ding 丟diu 东dong 吺dou 剢du
  23. 剬duan 垖dui 吨dun 多duo 妸e 诶ei 奀en 鞥eng 儿er 发fa 帆fan 匚fang 飞fei 分fen 丰feng
  24. 仏fo 紑fou 夫fu 旮ga 侅gai 甘gan 冈gang 皋gao 戈ge 给gei 根gen 刯geng 工gong 勾gou 估gu
  25. 瓜gua 乖guai 关guan 光guang 归gui 衮gun 呙guo 哈ha 还hai 佄han 夯hang 蒿hao 诃he 黒hei 拫hen
  26. 亨heng 叿hong 齁hou 乎hu 花hua 怀huai 欢huan 巟huang 灰hui 昏hun 吙huo 丌ji 加jia 戋jian 江jiang
  27. 艽jiao 阶jie 巾jin 仱jing 坰jiong 丩jiu 圧ju 姢juan 撅jue 军jun 咔ka 开kai 刊kan 闶kang 尻kao
  28. 苛ke 肎ken 劥keng 空kong 抠kou 扝ku 夸kua 蒯kuai 宽kuan 匡kuang 亏kui 坤kun 扩kuo 垃la 来lai
  29. 兰lan 啷lang 捞lao 仂le 雷lei 塄leng 唎li 嫾lian 簗liang 蹽liao 毟lie 拎lin 伶ling 溜liu 囖lo
  30. 龙long 瞜lou 撸lu 峦luan 掠lue 抡lun 啰luo 驴lv 略lve 妈ma 埋mai 颟man 牤mang 猫mao 孭me
  31. 沒mei 椚men 擝meng 咪mi 芇mian 喵miao 吀mie 民min 名ming 谬miu 摸mo 哞mou 呒mu 乸na 腉nai
  32. 囡nan 囔nang 孬nao 讷ne 馁nei 嫩nen 能neng 妮ni 拈nian 娘niang 鸟niao 捏nie 脌nin 宁ning 牛niu
  33. 农nong 羺nou 奴nu 奻nuan 挪nuo 女nv 噢o 讴ou 帊pa 拍pai 眅pan 乓pang 抛pao 呸pei 喷pen
  34. 匉peng 丕pi 囨pian 剽piao 氕pie 拼pin 乒ping 攴po 剖pou 扑pu 七qi 掐qia 扦qian 羌qiang 悄qiao
  35. 切qie 钦qin 青qing 卭qiong 丘qiu 区qu 奍quan 炔qv 夋qun 冄ran 穣rang 荛rao 惹re 人ren 扔reng
  36. 日ri 戎rong 禸rou 邚ru 撋ruan 甤rui 闰run 叒ruo 仨sa 毢sai 三san 桒sang 掻sao 色se 森sen
  37. 僧seng 杀sha 筛shai 山shan 伤shang 捎shao 奢she 申shen 升sheng 尸shi 収shou 殳shu 刷shua 衰shuai 闩shuan
  38. 双shuang 谁shui 吮shun 说shuo 厶si 忪song 凁sou 苏su 狻suan 夊sui 孙sun 莏suo 他ta 咍tai 坍tan
  39. 汤tang 仐tao 忑te 膯teng 剔ti 天tian 旫tiao 帖tie 厅ting 囲tong 偷tou 凸tu 猯tuan 推tui 吞tun
  40. 乇tuo 屲wa 歪wai 弯wan 尪wang 危wei 昷wen 翁weng 挝wo 乌wu 夕xi 虾xia 仙xian 乡xiang 灲xiao
  41. 些xie 心xin 星xing 凶xiong 休xiu 戌xu 吅xuan 削xv 坃xun 丫ya 咽yan 央yang 幺yao 耶ye 一yi
  42. 乚yin 応ying 哟yo 佣yong 优you 迂yu 囦yuan 曰yv 晕yun 帀za 灾zai 兂zan 赃zang 遭zao 则ze
  43. 贼zei 怎zen 増zeng 扎zha 夈zhai 枬zhan 弡zhang 钊zhao 蜇zhe 贞zhen 凧zheng 之zhi 中zhong 舟zhou 朱zhu
  44. 抓zhua 跩zhuai 专zhuan 妆zhuang 隹zhui 迍zhun 拙zhuo 孖zi 宗zong 邹zou 租zu 劗zuan 厜zui 尊zun 昨zuo
  45. ) do (
  46. set 字!字典长度!=%%a
  47. set /a 字典长度+=1
  48. )
  49. exit /b
  50. :py
  51. setlocal enabledelayedexpansion
  52. set "$=!%1!#"
  53. set N=&for %%a in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%a!. NEQ . set/aN+=%%a&set $=!$:~%%a!
  54. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
  55. rem 二分回溯法求字符串长度
  56. set/a length=N
  57. set "newstr="
  58. for /l %%a in (%length% -1 1) do (
  59. set char=!%1:~-%%a,1!
  60. set ret=!char!
  61. set m=0
  62. if !char! geq 吖 if !char! leq 咗 (
  63. for %%c in (256 128 64 32 16 8 4 2 1) do (
  64. set /a bak=m,m+=%%c
  65. for /l %%m in (!m! 999 %字典长度%) do (
  66. if !字%%m:~^,1! leq !char! (
  67. set bak=%%m
  68. set "ret= !字%%m:~1! "
  69. )
  70. )
  71. set m=!bak!
  72. )
  73. rem 二分法快速定位拼音
  74. )
  75. set newstr=!newstr!!ret!
  76. )
  77. for /f "delims=" %%a in ("!newstr!") do endlocal&set %2=%%a
  78. exit /b
复制代码

作者: CrLf    时间: 2015-8-11 01:02

顶楼代码改进自旧帖 http://www.bathome.net/viewthread.php?tid=14681,在算法上有大幅优化:
1、使用二分法快速定位在字典中的对应位置
2、使用二分回溯查表法计算字符串长度
3、将字典保存在伪数组中
4、利用特殊语法技巧化简流程

字典根据以下两贴的资料进行重新整理校对,更完整和准确:
http://www.bathome.net/viewthread.php?tid=36847
http://demon.tw/reverse/cmd-internal-if.html
作者: CrLf    时间: 2015-8-11 01:08

还有更快的算法吗?有木有人来挑战?仅限纯批
作者: aa77dd@163.com    时间: 2015-8-11 11:31

没运行你的代码, 但不知你是否充分考虑了边缘问题
  1. (echo 阿& echo 啊& echo 呵& echo 吖) | sort
  2. (echo 做& echo 坐& echo 昨) | sort
  3. if 坐 lss 昨 echo oh
复制代码

作者: 523066680    时间: 2015-8-11 11:57

噢,想起上次有一个取拼音开头的Excel宏函数
  1. Option Explicit
  2. Public Function LChin(Str As String) As Variant
  3.     On Error Resume Next
  4.     Str = StrConv(Str, vbNarrow)
  5.     If Asc(Str) > 0 Or Err.Number = 1004 Then LChin = ""
  6.     LChin = WorksheetFunction.VLookup(Str, [{"吖","a";"八","b";"嚓","c";"咑","d";"鵽","e";"发","f";"猤","g";"铪","h";"夻","j";"咔","k";"垃","l";"嘸","m";"旀","n";"噢","o";"妑","p";"七","q";"囕","r";"仨","s";"他","t";"屲","w";"夕","x";"丫","y";"帀","z"}], 2)
  7. End Function
复制代码

作者: CrLf    时间: 2015-8-11 15:01

回复 4# aa77dd@163.com


    试了下没问题啊,简表的格式是 [区间起始汉字][对应拼音]
作者: aa77dd@163.com    时间: 2015-8-11 16:21

本帖最后由 aa77dd@163.com 于 2015-8-11 16:27 编辑

回复 6# CrLf
  1. set input=坐下
  2. echo;%input%
  3. call :py input newstr
  4. echo !newstr!
  5. echo;
复制代码
得到的结果
  1. 坐下
  2. 坐 xia
复制代码
如果 "昨" 是 zuo 音的第一个字, 你的代码会把排序在 "昨" 后面的汉字都忽略掉而不给出拼音的翻译结果,  这个边界必须有不同的处理代码
  1. if !char! geq 吖 if !char! leq 昨
复制代码
应该改成
  1. if !char! geq 吖 if !char! leq "zuo 音的最后一个汉字"
复制代码

作者: CrLf    时间: 2015-8-11 17:07

回复 7# aa77dd@163.com


噢,是的
我擦,顺手一改反倒给改错了
感谢指正!
作者: Demon    时间: 2015-8-11 18:25

mark
作者: CrLf    时间: 2015-8-11 19:51

回复 5# 523066680


嗯,通用性也受同样的限制
不过“鵽”对应 e 错了,这个字是 duo
作者: aa77dd@163.com    时间: 2015-8-11 20:12

本帖最后由 aa77dd@163.com 于 2015-8-11 20:13 编辑

因为想到可以用 sort | findstr 来找到索引数字, 所以就实现了一下

没考虑特殊字符, zuo 音的最后一个字符不知道是什么, 如果遇到排在 昨 后面但没有读音的字符(可能就不是汉字吧, 当然也不是英文字母之类的), 这里也会处理成 有拼音 zuo, 嘿嘿

至于效率速度这些东东, 更木有考虑了
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. call :init
  4. set "str=你好, 世界 hello world 昨坐安按阿吖拼音汉字"
  5. set "PY="
  6. for /l %%i in (0 1 28) do (
  7.     set "chr=!str:~%%i,1!"
  8.     if "!chr!" lss "吖" (
  9.         set "PY=!PY!!chr!"
  10.     ) else (
  11.         for %%c in (!chr!) do if "!inds:%%c=!" neq "%inds%" (
  12.             for /f "skip=1 delims=:" %%a in ('(echo !inds!!chr!^)^|sort^|findstr /n "!chr!"') do set "PY=!PY! !$%%a! "
  13.         ) else (
  14.             for /f "delims=:" %%a in ('(echo !inds!!chr!^)^|sort^|findstr /n "!chr!"') do set "PY=!PY! !$%%a! "
  15.         )
  16.     )
  17. )
  18. set str
  19. set PY
  20. pause
  21. exit
  22. :init
  23. set "cnt=1"
  24. for %%a in (
  25. 吖a 哎ai 安an 肮ang 凹ao 八ba 挀bai 扳ban 邦bang 勹bao 萡be 陂bei 奔ben 伻beng 皀bi
  26. 边bian 标biao 憋bie 汃bin 仌bing 癶bo 卜bu 攃ca 猜cai 参can 仓cang 撡cao 刂ce 岑cen 噌ceng
  27. 叉cha 犲chai 觇chan 伥chang 抄chao 车che 抻chen 阷cheng 吃chi 冲chong 抽chou 出chu 欻chua 揣chuai 川chuan
  28. 刅chuang 吹chui 杶chun 逴chuo 呲ci 匆cong 凑cou 粗cu 汆cuan 崔cui 邨cun 搓cuo 咑da 呆dai 亻dan
  29. 当dang 刀dao 恴de 揼den 灯deng 仾di 嗲dia 敁dian 刁diao 爹die 丁ding 丟diu 东dong 吺dou 剢du
  30. 剬duan 垖dui 吨dun 多duo 妸e 诶ei 奀en 鞥eng 儿er 发fa 帆fan 匚fang 飞fei 分fen 丰feng
  31. 仏fo 紑fou 夫fu 旮ga 侅gai 甘gan 冈gang 皋gao 戈ge 给gei 根gen 刯geng 工gong 勾gou 估gu
  32. 瓜gua 乖guai 关guan 光guang 归gui 衮gun 呙guo 哈ha 还hai 佄han 夯hang 蒿hao 诃he 黒hei 拫hen
  33. 亨heng 叿hong 齁hou 乎hu 花hua 怀huai 欢huan 巟huang 灰hui 昏hun 吙huo 丌ji 加jia 戋jian 江jiang
  34. 艽jiao 阶jie 巾jin 仱jing 坰jiong 丩jiu 圧ju 姢juan 撅jue 军jun 咔ka 开kai 刊kan 闶kang 尻kao
  35. 苛ke 肎ken 劥keng 空kong 抠kou 扝ku 夸kua 蒯kuai 宽kuan 匡kuang 亏kui 坤kun 扩kuo 垃la 来lai
  36. 兰lan 啷lang 捞lao 仂le 雷lei 塄leng 唎li 嫾lian 簗liang 蹽liao 毟lie 拎lin 伶ling 溜liu 囖lo
  37. 龙long 瞜lou 撸lu 峦luan 掠lue 抡lun 啰luo 驴lv 略lve 妈ma 埋mai 颟man 牤mang 猫mao 孭me
  38. 沒mei 椚men 擝meng 咪mi 芇mian 喵miao 吀mie 民min 名ming 谬miu 摸mo 哞mou 呒mu 乸na 腉nai
  39. 囡nan 囔nang 孬nao 讷ne 馁nei 嫩nen 能neng 妮ni 拈nian 娘niang 鸟niao 捏nie 脌nin 宁ning 牛niu
  40. 农nong 羺nou 奴nu 奻nuan 挪nuo 女nv 噢o 讴ou 帊pa 拍pai 眅pan 乓pang 抛pao 呸pei 喷pen
  41. 匉peng 丕pi 囨pian 剽piao 氕pie 拼pin 乒ping 攴po 剖pou 扑pu 七qi 掐qia 扦qian 羌qiang 悄qiao
  42. 切qie 钦qin 青qing 卭qiong 丘qiu 区qu 奍quan 炔qv 夋qun 冄ran 穣rang 荛rao 惹re 人ren 扔reng
  43. 日ri 戎rong 禸rou 邚ru 撋ruan 甤rui 闰run 叒ruo 仨sa 毢sai 三san 桒sang 掻sao 色se 森sen
  44. 僧seng 杀sha 筛shai 山shan 伤shang 捎shao 奢she 申shen 升sheng 尸shi 収shou 殳shu 刷shua 衰shuai 闩shuan
  45. 双shuang 谁shui 吮shun 说shuo 厶si 忪song 凁sou 苏su 狻suan 夊sui 孙sun 莏suo 他ta 咍tai 坍tan
  46. 汤tang 仐tao 忑te 膯teng 剔ti 天tian 旫tiao 帖tie 厅ting 囲tong 偷tou 凸tu 猯tuan 推tui 吞tun
  47. 乇tuo 屲wa 歪wai 弯wan 尪wang 危wei 昷wen 翁weng 挝wo 乌wu 夕xi 虾xia 仙xian 乡xiang 灲xiao
  48. 些xie 心xin 星xing 凶xiong 休xiu 戌xu 吅xuan 削xv 坃xun 丫ya 咽yan 央yang 幺yao 耶ye 一yi
  49. 乚yin 応ying 哟yo 佣yong 优you 迂yu 囦yuan 曰yv 晕yun 帀za 灾zai 兂zan 赃zang 遭zao 则ze
  50. 贼zei 怎zen 増zeng 扎zha 夈zhai 枬zhan 弡zhang 钊zhao 蜇zhe 贞zhen 凧zheng 之zhi 中zhong 舟zhou 朱zhu
  51. 抓zhua 跩zhuai 专zhuan 妆zhuang 隹zhui 迍zhun 拙zhuo 孖zi 宗zong 邹zou 租zu 劗zuan 厜zui 尊zun 昨zuo
  52. ) do (
  53.         set "tt=%%a"
  54.     set "inds=!inds!!tt:~0,1!&echo;"
  55.         set /a cnt+=1
  56.     set "$!cnt!=!tt:~1!"
  57. )
  58. exit /b
复制代码

作者: CrLf    时间: 2015-8-11 20:18

回复 11# aa77dd@163.com


哈,这思路也不错,算法好记
zuo 音的最后一个字是咗

整个列表顺序是这样的:
  1. ○ ling
  2. 吖 a|ya
  3. ...
  4. 咗 zo|zuo
  5. 乤 hal
复制代码

作者: CrLf    时间: 2015-8-11 20:28

回复 11# aa77dd@163.com


    我想也可以考虑先全部拆字输出,然后排序解析,在伪hash表中为每个字设置对应拼音,再回过头来逐字处理,这样算法会变得比较复杂,但能节省反复运行 sort.exe 和 findstr.exe 的耗时
作者: MCRGZN    时间: 2015-8-13 17:18

不错不错不错不错不错
作者: MCRGZN    时间: 2015-8-13 17:19

不错不错不错不错不错
作者: wskwfkbdn    时间: 2016-1-19 00:00     标题: 标题

回复 1# CrLf
纯p的文字转拼音挺不错,如果是 “简123单”,你看转转结果怎么样。
作者: CrLf    时间: 2016-1-19 01:05

回复 16# wskwfkbdn


测试得到的输出如下:
  1. 简123单
  2. jian 123 dan
复制代码
好像没遇到问题
作者: wskwfkbdn    时间: 2016-1-19 13:50

回复 17# CrLf


    挺好的,赞 +1




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