Python正则表达式处理中文文本文件一要注意编码,二要注意贪婪匹配模式。
以广为流传的人民日报分词语料为例:
人民网/nz 1月1日/t 讯/ng 据/p 《/w [纽约/nsf 时报/n]/nz 》/w 报道/v ,/w 美国/nsf 华尔街/nsf 股市/n 在/p 2013年/t 的/ude1 最后/f 一天/mq 继续/v 上涨/vn ,/w 和/cc [全球/n 股市/n]/nz 一样/uyy ,/w 都/d 以/p [最高/a 纪录/n]/nz 或/c 接近/v [最高/a 纪录/n]/nz 结束/v 本/rz 年/qt 的/ude1 交易/vn 。/w
《/w [纽约/nsf 时报/n]/nz 》/w 报道/v 说/v ,/w 标普/nz 500/m 指数/n 今年/t 上升/vi 29.6%/m ,/w 为/p 1997年/t 以来/f 的/ude1 最大/gm 涨幅/n ;/w [道琼斯/ntc 工业/n 平均/a 指数/n]/nz 上升/vi 26.5%/m ,/w 为/p 1996年/t 以来/f 的/ude1 最大/gm 涨幅/n ;/w [纳斯/nrf 达/v 克/q]/nz 上涨/vi 38.3%/m 。/w
就/d 12月31日/t 来说/uls ,/w 由于/p 就业/vn 前景/n 看好/v 和/cc [经济/n 增长/v]/nz 明年/t 可能/v 加速/vn ,/w 消费者/n 信心/n 上升/vi 。/w 工商/n 协进会/nis (/w ConferenceBoard/x )/w 报告/n ,/w 12月/t 消费者/n 信心/n 上升/vi 到/v 78.1/m ,/w 明显/a 高于/v 11月/t 的/ude1 72/m 。/w
另据/nz 《/w [华尔街/nsf 日报/n]/nz 》/w 报道/v ,/w 2013年/t 是/vshi 1995年/t 以来/f [美国/nsf 股市/n]/nz 表现/v 最好/d 的/ude1 一年/mq 。/w 这/rzv 一年/mq 里/f ,/w 投资/v [美国/nsf 股市/n]/nz 的/ude1 明智/a 做法/n 是/vshi 追/v 着/uzhe “/w 傻钱/nz ”/w 跑/v 。/w 所谓/v 的/ude1 “/w 傻钱/nz ”/w 策略/n ,/w 其实/d 就是/v 买入/vn 并/cc 持有/v 美国/nsf 股票/n 这样/rzv 的/ude1 普通/a 组合/vn 。/w 这个/rz 策略/n 要/v 比/p [对冲/vn 基金/n]/nz 和/cc 其它/rz 专业/n 投资者/nnd 使用/v 的/ude1 更为/d 复杂/a 的/ude1 投资/vn 方法/n 效果/n 好/a 得/ude3 多/a 。/w (/w 老/a 任/v )/w
编码
文本文件编码是UTF-8,读入到Python中还是UTF-8,也就是<type 'str'>。utf8
下,每个汉字占据3个字符位置,正则式为[\x80-\xff]{3}
。
所以匹配的正则表达式应当是
r'(([\x80-\xff]{3})+)\s*/\s*([a-zA-Z]+)'
其它编码参考:
一点经验
可以使用
repr()
函数查看字串的原始格式。这对于写正则表达式有所帮助。Python 的
re
模块有两个相似的函数:re.match(), re.search
。两个函数的匹配过程完全一致,只是起点不同。match
只从字串的开始位置进行匹配,如果失败,它就此放弃;而search
则会锲而不舍地完全遍历整个字串中所有可能的位置,直到成功地找到一个匹配,或者搜索完字串,以失败告终。如果你了解match
的特性(在某些情况下比较快),大可以自由用它;如果不太清楚,search
通常是你需要的那个函数。从一堆文本中,找出所有可能的匹配,以列表的形式返回,这种情况用
findall()
这个函数。例子见后面的代码。
utf8
下,每个汉字占据3个字符位置,正则式为[\x80-\xff]{3}
,这个都知道了吧。
unicode
下,汉字的格式如\uXXXX
,只要找到对应的字符集的范围,就能匹配相应的字串,方便从多语言文本中挑出所需要的某种语言的文本。不过,对于像日文这样的粘着语,既有中文字符,又有平假名片假名,或许结果会有所偏差。两种字符类可以并列在一起使用,例如,平假名、片假名、中文的放在一起,
u"[\u4e00-\u9fa5\u3040-\u309f\u30a0-\u30ff]+"
,来自定义所需要匹配的文本。匹配中文时,正则表达式和目标字串的格式必须相同。这一点至关重要。或者都用默认的
utf8
,此时你不用额外做什么;如果是unicode
,就需要在正则式之前加上u""
格式。
贪婪模式
贪婪模式下会优先匹配出最长的串,然后是次长的串,如 人民网 网。所以要注意排除第二个“网”。
输出:
人民网 日 讯 据 《 纽约 时报 》 报道 , 美国 华尔街 股市 在 年 的 最后 一天 继续 上涨 , 和 全球 股市 一样 , 都 以 最高 纪录 或 接近 最高 纪录 结束 本 年 的 交易 。
《 纽约 时报 》 报道 说 , 标普 指数 今年 上升 , 为 年 以来 的 最大 涨幅 ; 道琼斯 工业 平均 指数 上升 , 为 年 以来 的 最大 涨幅 ; 纳斯 达 克 上涨 。
就 日 来说 , 由于 就业 前景 看好 和 经济 增长 明年 可能 加速 , 消费者 信心 上升 。 工商 协进会 ( ) 报告 , 月 消费者 信心 上升 到 , 明显 高于 月 的 。
另据 《 华尔街 日报 》 报道 , 年 是 年 以来 美国 股市 表现 最好 的 一年 。 这 一年 里 , 投资 美国 股市 的 明智 做法 是 追 着 “ 傻钱 ” 跑 。 所谓 的 “ 傻钱 ” 策略 , 其实 就是 买入 并 持有 美国 股票 这样 的 普通 组合 。 这个 策略 要 比 对冲 基金 和 其它 专业 投资者 使用 的 更为 复杂 的 投资 方法 效果 好 得 多 。 ( 老 任 )
如果是其他语言可以试试:(\w+)\s*\/\s*([a-zA-Z]+)
当然,这个表达式还不完美,数字和英文以及半角标点都被干掉了。考虑到这些符号太多了,所以我觉得还不如用空格切割。
([\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\u4e00-\u9fa5\w]+)/([a-z]+)
博主您好,我也遇到了问题,这是我的代码
test=re.compile(r'(([x80-xff]{3})+)s*/s*([a-zA-Z]+)’)
result=test.findall(‘a123jdsdf你好の??’)
print result
我把您的表达式拿了过来,Python27下执行结果是空的,您能看出来是为什么吗
博主可以给一下2014人民日报的语料库吗? 网上找了半天没有找到
https://github.com/hankcs/HanLP/wiki/%E8%AE%AD%E7%BB%83%E5%88%86%E8%AF%8D%E6%A8%A1%E5%9E%8B#%E8%AF%AD%E6%96%99%E6%A0%BC%E5%BC%8F