分类: C/C++
2008-04-23 21:50:31
集思广义支持中文的正则表达式
作者:
初衷——我想说的
大家好!
我所知道的正则表达式库有:boost的,GNU的,VC7带的ATL中的和微软发布的greta。我使用过后三种,greta使用时间最短(才两天)。
现在我来说说我的感受
GNU的正则表达式根本就不支持多字节码,设置连UNICODE都不支持,在parse阶段就会非法操作。在软件全球化的今天,实在不是一个好现象。优点是支持的语法完备。
ATL中的正则表达式不完全支持多字节码,可以完善的支持UNICODE。不过,此正则表达式书写非常清晰,没有用到STL里面任何高深的东西,也没有用到模板中特别高深的东西(我认为这才是C 的发展之道,毕竟,聪明人是少数——大部分是平庸的人,曲高寡合,总有一天会被大多数程序员抛弃,剩下一帮高手顾影自怜),所以,通过非常微小和容易的更改就可以完善支持多字节码。缺点是不支持{n,m}语法,不支持递归语法,如:"([^\\"]*(\\.)*[^\\"]*)*"。最后一个*是不被支持的。
greta能完善的支持单字节码和UNICODE,语法也完善,而且据说普遍情况下速度也快,不过,把部分实现放cpp里导致不能同时使用单字节码和UNICODE编码,posix和perl语法,解决办法还算简单:把cpp改名为inl,在.h里include这个inl,再修改一点别的东西就可。问题是,它没有支持多字节码的实现,我仔细看看了,似乎通过自己写一个多字节码的迭代子,可以解决这个问题,因为他支持basic_string。
接下来的问题是:STL如何支持多字节码的?我没有在SGI-STL,STLPort453中找到关于多字节码的东西。basic_string默认只实现了char,wchar_t的base_string。而要自己实现一个迭代子,我又不知道如何下手。
我现在的需求是
需要正则表达式支持类似这样的语法:
“/汉字[ ] [^ , ,] [ ]*[,,][ ]*[^ , ,] ”
以匹配“/汉字 兰征鹏 ,正则表达式”。
使用STL进行字符串搜索都有问题,比如在一篇文章中搜索“正则”,很可能就把三个汉字的中间四个字节匹配上了。出现这样的情况,让人哭笑不得。
有这方面经验的或对STL比较熟悉的同仁,请勿吝啬指导
致
礼!
lanzhengpeng
2004-06-02
_______________________________________________
Cpp mailing list
在C/C 中如果想要使用与Perl兼容的regexp库,一个选择是Boost,另一个选择是PCRE库。Boost中的regex算法最近做了改近,平均效率比以前的版本提高了10倍,不过用起来可能比较麻烦。PCRE已经很成熟了,Apache/Postfix/PHP/Python都用它。我认为应该优先考虑。不过我自己没有在Windows下编译过,不是很有把握。
See
我个人很喜欢Ruby中的正则表达式功能,功能强,速度也很不错。因为Ruby是日本人发明的,处理东亚大字符集没有任何问题。Ruby与C/C 接口很容易,但是为了这个小功能加入Ruby,似乎有点小题大做了。Perl我不熟悉。Lua独创了一套模式匹配语法,而且Lua天生就是要嵌入到C/C 中去的,性能比Perl/Ruby/Python都快的多。Lua的模式匹配语法有点怪,解决lanzhengpeng的问题好像是足够的,不过跟标准regex语法完全不同。
我个人的感觉,不如静下心来写一个iterator,应该是很容易的。不过我也很久没干过这种事情了,也就泛泛的说说算了。
孟岩
_______________________________________________
Cpp mailing list
发件人: kyo
发送时间: 2004年6月2日 11:19
收件人: ''C Discuss Group''
主题: RE: [cpp]正则表达式和多字节码的问题
兰兄的经历我很有经验,以前也曾经努力寻找一套好用的正则表达式的C 库,然而用过以后都不太满意。正则表达式中公认的perl是做的最好的(现在很多库都声称可以支持perl的正则表达式),比如懒惰匹配就很有用。
如果兰兄不是必须用C 做的话,可以用内嵌python引擎,然后用python里的正则表达式module re按你的要求的话,需要使用python 2.4以上版本,因为中文的unicode在2.4才支持(2.4还没有release。)
关于C 汉字查找的问题最近大话西游也遇到,因为要限制经济频道里的说话必须包含“卖”。要精确判断的话,需要先把char*或string的字符串先用MultiByteToWideChar转为 WCHAR或wstring, 然后再查找。
希望对你有用。
_______________________________________________
Cpp mailing list
孟岩,您好!
See
多谢!
我个人的感觉,不如静下心来写一个iterator,应该是很容易的。不过我也很久没干过这种事情了,也就泛泛的说说算了。
我着手写了一下,似乎我写一个iterator不起作用,需要把base_string也一起写了。而且有个很大的问题: 操作跟--操作不一致。 的时候我可以很容易判断当前字节是否是多字节吗,从而地址 1还是 2。但是,--的时候就不是那么好做了(考虑到支持如GIB5——其汉字的后半字节编码跟英文有重叠),如果单纯的地址-1,会不会出现问题,这个迭代子是否还是random_iterator?
致
礼!
lanzhengpeng
2004-06-02
_______________________________________________
Cpp mailing list
发送时间: 2004年6月2日 15:53
收件人: C Discuss Group
主题: Re[2]: 答复: [cpp]正则表达式和多字节码的问题
Hello lanzhengpeng,
还是转一下吧, 转成 wstring。
我想到另外一个问题, 也是我前段干过的。就是英文有 stricmp, 中文是否也应该有一个模糊查找. 比如忽略掉同音字的。有时候也不用忽略所有同音字,高频字一般即使同音也不会混用
。一些不常用到的字容易用同音别字代替。另外汉字有多音字的问题,使这种模糊匹配的算法变得复杂。
我曾经花了一下午的时间整理资料,把大部分 GBK 字集里的汉字的汉语拼音都列出来的(包括声调),包括一字多音的。
还有一种最常用的 1000 多字的按使用频率排列的表。
有没有人感兴趣呀 :)
Best regards,
Cloudwu
[一人之断制, 所见有限, 犹目之一瞥, 岂能尽万物之情乎]
_______________________________________________
Cpp mailing list
关于C 汉字查找的问题最近大话西游也遇到,因为要限制经济频道里的说话必须包含“卖”。要精确判断的话,需要先把char*或string的字符串先用MultiByteToWideChar转为
WCHAR或wstring, 然后再查找。这样只能判断有和无,实际上我需要精确位置。
是可以精确查找的呀。
另外是否可以嵌入其他东西:我觉得没有必要,实际那些脚本语言最后也通过C/C 来做的,搞不好还就是用的我们已知的东西。而且正则表达式如此有用,以至于我到处都在使用——无论程序大小。如果为此在那些众多的程序中嵌入一个脚本,也是我所不愿意的。
_______________________________________________
Cpp mailing list
kyo,您好!
关于C 汉字查找的问题最近大话西游也遇到,因为要限制经济频道里的说话必须包含“卖”。要精确判断的话,需要先把char*或string的字符串先用MultiByteToWideChar转为
WCHAR或wstring, 然后再查找。这样只能判断有和无,实际上我需要精确位置。
另外是否可以嵌入其他东西:我觉得没有必要,实际那些脚本语言最后也通过C/C 来做的,搞不好还就是用的我们已知的东西。而且正则表达式如此有用,以至于我到处都在使用——无论程序大小。如果为此在那些众多的程序中嵌入一个脚本,也是我所不愿意的。
致
礼!
lanzhengpeng
2004-06-02
_______________________________________________
Cpp mailing list
Hello lanzhengpeng,
用什么多字节,不但麻烦,效率又低,转换成unicode再处理拉。
大家都这么推荐,我着手做一下吧。多字及码到UNICODE的位置影射也应该不难为什么要转成 unicode? 我觉得转成双字节就够了多一步转换干什么?
Best regards,
cloudwu
[凡是有良好教养的人有一禁诫:勿发脾气]
_____________________________________________
Analyst,您好!
用什么多字节,不但麻烦,效率又低,转换成unicode再处理拉。大家都这么推荐,我着手做一下吧。多字及码到UNICODE的位置影射也应该不难。
致
礼!
lanzhengpeng
2004-06-03
_______________________________________________
Cpp mailing list
kyo,您好!
关于C 汉字查找的问题最近大话西游也遇到,因为要限制经济频道里的说话必须包含“卖”。要精确判断的话,需要先把char*或string的字符串先用MultiByteToWideChar转为 WCHAR或wstring, 然后再查找。这样只能判断有和无,实际上我需要精确位置。
是可以精确查找的呀。
我曾经做过一个小工具,提取并修改代码中的文字部分,并将文字汇总到一个文件里,需要本地化的时候,修改这个文件就可。比如:LANGUAGE(0,"我曾经做过一个小工具");正则表达式应该很容易抽取出0,并且将0替换成一个其他的数值(就是后面的字符在文件中排序的编号)。如果转换过后,我怎么知道原来的位置呢?
致
礼!
lanzhengpeng
2004-06-03
_______________________________________________
Cpp mailing list
大家好!
近日空闲了,着手写个正则表达式解析的东西吧,不求速度,只求满足我的要求。在我完成一定阶段的编码后,会交付源代码给大家测试。
现在问几个问题:
“^”作为匹配起始的时候:
一、在单行模式下(即全文中可以包含换行符号“\n”,但是“$”不匹配“\n”,而是匹配结束。同时,“.”可匹配“\n”),“^”可否写在表达式的中间,如此必然没有任何可匹配的东西。这个时候是否作为语法错误?
二、在多行模式下,“^”是作为匹配的起始地址还是说匹配“\n”的后一个字符?我比较趋向于匹配起始地址
三、在多行模式下,“$”可否匹配匹配串的结束?还是只匹配“\n|\r\n”
四、“^$”是否作为语法错误处理?如果不作为语法错误,是匹配一个空串还是什么都不匹配?
这些疑问,在各个正则表达式库或各个工具(如VC,UEdit)都有不同的处理方案。
另外,我暂时没有找到正则表达式详细介绍的资料(如rfc或编译原理的书籍),烦请哪位达人提供一份资料,中文最好,英语也可,其它语言不考虑。
_______________________________________________
Cpp mailing list
关于C 汉字查找的问题最近大话西游也遇到,因为要限制经济频道里的说话必须包含“卖”。要精确判断的话,需要先把char*或string的字符串先用MultiByteToWideChar转为
WCHAR或wstring, 然后再查找。这样只能判断有和无,实际上我需要精确位置。
是可以精确查找的呀。
我曾经做过一个小工具,提取并修改代码中的文字部分,并将文字汇总到一个文件里,需要本地化的时候,修改这个文件就可。比如:LANGUAGE(0,"我曾经做过一个小工具");
正则表达式应该很容易抽取出0,并且将0替换成一个其他的数值(就是后面的字符在文件中排序的编号)。如果转换过后,我怎么知道原来的位置呢?
wchar 查找到位置后,然后把它逐个转换为char不就知道了嘛,哈哈 :B
致
礼!
lanzhengpeng
2004-06-05
_______________________________________________
Cpp mailing list
我是初学者, 也来添乱:
一.在单行模式下^ $都只表述位置概念(开始, 结束), 而不匹配具体的任何字串,所以$当然不匹配"\n", ^写在中间是可以匹配的, 比如我写 a?^b 或者是a{0}^b时, bcd是可以匹配的, 当然把开始位置的匹配写到其他地方不是一个好习惯, 但是也许也不应该禁止吧?
二.多行模式下^匹配"\n"的下一个字符, 比如^\d 和abcd\n123匹配, 而$匹配"\n"的上一个字符, 比如is$ 和his\nhere匹配
。
三.不是很理解所说的, 应该是指is$是否和hr\nhis这样的字串匹配吧? 答案是yes多行模式下使$舆行的末尾匹配(而不止是字符串的末尾), ^舆行的开始匹配(而不止是字符串的开始)
四.不应该判为非法, 单行模式下 ^$匹配"" 多行模式下匹配"aaa\n\naaa"(空行)只用egrep测试过^_^
书就有一本了, 来可欣这边就可以看到啦...《regular expression》
_____________________________________________
Cpp mailing list
我想说的
我相信,这个世界上的正则表达式解析库远远不止我知道的这些,但是,愿意开源的就很少了。开源的库其质量也是参差不齐,或着重点不同。特别引人注目的是,在所有这些已知的代码库中,没有一个是中国程序员写的。我希望打破这种局面,并且注重功能和支持多字节码(不仅仅是东亚大字符集),速度是其次——因为我的功底不够,对正则表达式不是非常熟悉,对有限自动机也没有理解透彻。
如果你要说我这个正则表达式语法不正统,那么,我会说你长得不像人——因为我才是标准的人样。
请勿散播造车不必从轮子造起的论调,我有很多大道理,但我不愿意写。公司领导对这个开放代码持有异议,不过,由于此代码库没有用在公司任何项目上,并且我坚持在家里完成代码的编码工作(这篇文章倒是在公司机器上写的),因此,此代码库不存在其他的版权纠纷,
你可以在遵守原始作者申明的前提下放心的分发、修改和使用。这个代码库必然还存在我不知道的缺陷——功能上的,安全上的,易用性上的......不管如何,我希望你在拥有良好心态前提下,将你发现的缺陷和你的想法告诉我:
兰征鹏
2004-6-16