重读红宝书(二):你的中文正则表达式是正确的吗?

698 阅读2分钟

This message is used to verify that this feed (feedId:98939115340705792) belongs to me (userId:j6-duTaXe_0xcc1a7oCk6). Join me in enjoying the next generation information browser follow.is.

[\u4e00-\u9fa5] 是正确的吗?

随便在一个搜索引擎上搜索中文正则表达式,99%都会出现[\u4e00-\u9fa5]这样的答案。但是,这个答案真是正确的吗?

正则表达式/[\u4e00-\u9fa5]/的意思是匹配 Unicode 中零号平面 U+4E00 到 U+9fa5 所有符号, 也就是不只会匹配中文,比如

/[\u4e00-\u9fa5]/.test('空き領域') // true

中日韩统一表意文字(英语:CJK Unified Ideographs),也称统一汉字、统汉码(英语:Unihan),目的是要把分别来自中文、日文、韩文、越南文、壮文、琉球文中,起源相同、本义相同、形状一样或稍异的表意文字,在ISO 10646及万国码标准赋予相同编码。

当然我们需要关注的关键点不在这里,看下下面的例子:

/[\u4e00-\u9fa5]/.test('龫') // false
/[\u4e00-\u9fa5]/.test('龦') // false
/[\u4e00-\u9fa5]/.test('鿏') // false

为什么都不能匹配了呢?

image.png

实际上[\u4e00-\u9fa5]能匹配的文字只有Unicode 1.0.1版本收录进来的中日韩统一表意文字。而 3.1 版本之后的中日韩统一表意文字是都没有包含的。其中还有很多是人名地名的汉字。

image.png 图片引自维基百科

所以这个表达式即对,也不对。从1992年6月到2001年3月之间确实是正确的。但就现在来说确实不够与时俱进了。

正确的中文正则

既然知道问题出在哪了,就肯定会有人造轮子解决问题。 比如

这样需要作者在Unicode更新时及时更新仓库,然后使用者也同步更新。

但这样维护成本太大了,难道没有一个一劳永逸的办法吗?

托现代浏览器和ES规范更新的福,还真有简单的办法。

/\p{Unified_Ideograph}/u.test('龫鿏龦') // true

这是一个不需要维护的正则表达式,其中\u是 ECMAScript 2015 定义的正则表达式标志,意味着将表达式作为 Unicode 码点序列。\p是ECMAScript 2018 定义的正则表达式 Unicode 属性转义。

如果浏览器不支持 Unicode 属性转义正则表达式,可以使用 @babel 支持,使用 7.7 版本的 @babel/env 即可自动打开。