按:本文使用的RegexBuddy为3.1.0(完全)版,并非最新版3.1.1(截至2008.08.23)。需要该版本的请在这篇文章后留言。
注:参考www.regular-expressions.info的风格,更新了本模板的style.css文件,加入了与正则式代码相关的格式:
- 正则式格式举例:[a-z]+@[a-z]+?/.[a-z]+
- 匹配格式举例:pig@animals.com和chicken@birds.com
- 普通文本格式举例:这是一些普通文本。hello regex world. pig@animals.com和chicken@birds.com
可以这样使用:在字符串这是一些普通文本。hello regex world. pig@animals.com和chicken@birds.com使用正则式[a-z]+@[a-z]+?/.[a-z]+加以匹配,得到的结果为:pig@animals.com和chicken@birds.com。
极端粗放型:点号其实是近乎万能的,可以匹配任何字符,限制只在于换行符的匹配上。匹配中文自然不在话下。作为可有可无的背景符,一个.*就能匹配掉包括中文在内的全部字符。这当然是一种极端的情况,因为这样显示不出中文字符串的特性。这不是本文要探讨的。
极端集约型:如果搜索特定文本,例如在一二三四五六七八九十拾佰百千仟万亿中匹配十拾, 直接使用m/十拾/就能搞定。这同样不是本文要探讨的。与/w能匹配英文字母一样,本文想找的是能够匹配所有汉字,而不匹配其它文本的一种简写方式。
普适型型:由于汉字属于Unicode,我们就从unicode里面找。在Unicode Regular Expressions,列出了unicode的许多种表达方式。搜索chinese,找到如下一行:
Writing Systems | Blocks |
… | … |
Chinese | CJK Unified Ideographs, CJK Unified Ideographs Extension A, CJK Compatibility Ideographs, CJK Compatibility Forms, Enclosed CJK Letters and Months, Small Form Variants, Bopomofo, Bopomofo Extended |
关于CJK的含义,是指中日韩统一表意文字(Chinese Japanese Korean Unified Ideographs),可以参考百度释义,或wiki词条。
再查了一下regular expressions,查到其unicode一节有这样的内容:
/p{InCJK_Unified_Ideographs}: U+4E00..U+9FFF
看到这里,我想起了以前写的《匹配用户名的asp正则表达式(包括中文)》一文中,提到的中文匹配为[/u4e00-/u9fa5],原来是有其对应的速记方式的,虽然两者有最后一组字符的差异。看附图可见U+9fa5,最后一个汉字的模样。 此序列的第一位,U+4e00,是汉字一。
自定义:到目前为止,相当于给汉字找到了官方的身份和说法,使用/p{InCJK_Unified_Ideographs}就能匹配所有的中文字符。我们其实也可以将一些重复出现的东西,封装起来,以备使用。例如,对于阿拉伯数字,我们有/d可以用。对于中文数字一二三四等等,我们有没有办法呢?
$zh_digit=qr/一|二|三|四|五|六|七|八|九|十|零|〇|百|千|万|亿|佰|仟|壹|贰|叁|肆|伍|陆|柒|捌|玖|拾/; $str="人民币五十一万零三百元整。大写:伍拾壹万零三佰元整。"; while($str =~ s/((?:$zh_digit)+)//) { print $1."/n"; }
其输出结果见附图。
结论
可以使用/p{InCJK_Unified_Ideographs}匹配任意中文字符。在不支持该种标记方式时,也可以使用[/u4e00-/u9fa5]加以匹配。
关于文正则表达式,我觉得尚未穷其奥秘。以前在linux(utf8编码)下,编写scim输入平台的郑码码表时,匹配中文所使用的正则表达式为[/x80-/xff]{3},也能很好地工作。请参阅此文:龙文郑码码表 for scim。其原理我尚不清楚,留待之后有时间研究。如有知情者,也请不吝赐教,先行谢过。