如何用正则表达式匹配汉字的所有相关字符

📝 ✏️ 📌
如何用正则表达式匹配汉字的所有相关字符

一个看似简单的需求,但网上流传甚广的[u4e00-u9fa5]其实有点问题。

从维基百科上 Unicode 页面的歴史章节给出的码表范围就能发现不对劲:中文互联网流传甚广的[u4e00-u9fa5]应该是只计算了【CJK Unified Ideographs】内的汉字,但这部分的内容其实只占了全部汉字的五分之一。虽然CJK Unified Ideographs 以使用频率来分区,但如果是开发语言文字相关的专业工具的话,最好全面覆盖所有相关字符。

範囲

名称

字数

U+4E00 - U+9FFF

CJK Unified Ideographs

20,992

U+3400 - U+4DBF

CJK Unified Ideographs Extension A

6,592

U+20000 - U+2A6DF

CJK Unified Ideographs Extension B

42,720

U+2A700 - U+2B738

CJK Unified Ideographs Extension C

4,154

U+2B740 - U+2B81D

CJK Unified Ideographs Extension D

222

U+2B820 - U+2CEA1

CJK Unified Ideographs Extension E

5,762

U+2CEB0 - U+2EBE0

CJK Unified Ideographs Extension F

7,473

U+30000 - U+3134A

CJK Unified Ideographs Extension G

4,939

U+31350 - U+323AF

CJK Unified Ideographs Extension H

4,192

U+2EBF0 - U+2EE5F

CJK Unified Ideographs Extension I

622

合計

97,668

如果遇到了 UniCode 相关的问题,最好的方法还是查阅 Unicode 官方提供的文档 Unicode 15.1 Character Code Charts。

下面给一个Python实现的例子:

"""匹配汉字相关字符"""

import re

# noinspection RegExpDuplicateCharacterInClass

ideographs_reg = re.compile(

r"""(?P[\u4E00-\u9FFF])|

(?P[\u3400-\u4DBF])|

(?P[\u20000-\u2A6DF])|

(?P[\u2A700-\u2B738])|

(?P[\u2B740-\u2B81D])|

(?P[\u2B820-\u2CEA1])|

(?P[\u2CEB0-\u2EBE0])|

(?P[\u30000-\u23134A])|

(?P[\u31350-\u323AF])|

(?P[\u2EBF0-\u2EE5F])|

(?P[\uF900-\uFAFF])| # 兼容区:([\x{F900}-\x{FAD9}])

(?P[\u2F800-\u2FA1F])| # 兼容扩展区:([\x{2F800}-\x{2FA1D}])

(?P[\u2F00-\u2FDF]) | # 康熙部首:([\x{2F00}-\x{2FD5}])

(?P[\u2E80-\u2EFF]) | # 部首扩展:([\u2E80-\u2EF3])

(?P[\u31c0-\u31ef]) | # 汉字笔画:([\u31C0-\u31E3])

(?P[\u2FF0-\u2FFF]) #汉字结构:([\u2FF0-\u2FFB])

(?P[\u3100-\u312F])| # 汉语注音:([\u3105-\u312F])

(?P[\u31A0-\u31BF])| # 注音扩展:([\u31A0-\u31BA])

(?P[\uE000-\uF8FF])| # 私有区:([\uE000-\uF8FF])

(?P[\uF0000-\uFFFFF])| # 私用PUA-A:([\uF0000-\uFFFFF])

(?P[\u100000-\u10FFFD])| # 私用PUA-B:([\u100000-\u10FFFF])

"""

)

def match_chinese_ideographs(input_text: str) -> bool:

"""匹配是否含有汉字相关字符

Args:

input_text (str): 需要匹配的字符串

Returns:

只要包含汉字相关的字符就返回 True

"""

result = False

for char in input_text:

if re.search(ideographs_reg, char) is not None:

print(re.match(ideographs_reg, char).groupdict())

result = True

return result

match_chinese_ideographs("食物")

补充

感谢 amob 提供的建议:

我刚刚看到你博客写的关于正则匹配汉字的文章,我个人对此有些经验(无聊处理过一些生僻字特多的词典)。目前\p{han}还只是基于Unicode 13.0的,许多新汉字都无法匹配,\p{Unified_Ideograph}/u没用过,估计匹配不了一些特殊情况。

经站内高人jcz777指点,目前最理想的匹配码位如下:

基本区:([\x{3007}\x{4e00}-\x{9fff}])

A区:([\x{3400}-\x{4DBF}])

B区:([\x{20000}-\x{2A6DF}])

C区:([\x{2A700}-\x{2B73F}])

D区:([\x{2B740}-\x{2B81F}])

E区:([\x{2B820}-\x{2CEA1}])

F区:([\x{2CEB0}-\x{2EBE0}])

G区:([\x{30000}-\x{3134A}])

H区:([\x{31350}-\x{323AF}])

I区:([\x{2EBF0}-\x{2EE5F}])

兼容区:([\x{F900}-\x{FAD9}])

兼容扩展区:([\x{2F800}-\x{2FA1D}])

康熙部首:([\x{2F00}-\x{2FD5}])

汉字笔画:([\x{31C0}-\x{31E3}])

汉字结构:([\x{2FF0}-\x{2FFB}])

汉语注音:([\x{3105}-\x{312F}])

注音扩展:([\x{31A0}-\x{31BA}])

部首扩展:([\x{2E80}-\x{2EF3}])

私有区:([\x{E000}-\x{F8FF}])

私用PUA-A:([\x{F0000}-\x{FFFFF}])

私用PUA-B:([\x{100000}-\x{10FFFF}])

再算上这几个,

𝍲、𝍳、𝍳、𝍴、𝍵

〡、〢、〣、〤、〥、〦、〧、〨、〩、〸

参考

JavaScript 正则表达式匹配汉字:[[Python]]没有这篇文章的提到的/\p{Unified_Ideograph}/u、和/\p{Script=Han}/u类似的方法,感觉可以写一个第三方库的价值(摊手

Python: 组合方式构建复杂正则:介绍了一种在实际开发场景下,如何构建易于修改和调试的正则用法。

🔗 相关推荐

✨ 💡 🎯
蝾螈怎么繁殖
365bet体育官网开户

蝾螈怎么繁殖

📅 10-02 👀 4640
您所访问的页面不存在
beat365官方

您所访问的页面不存在

📅 07-31 👀 8959
梦幻西游命归术(梦幻命疗术和气归术哪个好)
365bet体育官网开户

梦幻西游命归术(梦幻命疗术和气归术哪个好)

📅 07-26 👀 9902