2020的今天,[\u4e00-\u9fa5]还能匹配到所有中文吗?

19,113 阅读2分钟

了解一下下unicode编码

Unicode(中文:万国码、国际码、统一码、单一码)是电脑科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。 Unicode 伴随著通用字符集的标准而发展,同时也以书本的形式[1]对外发表。Unicode 至今仍在不断增修,每个新版本都加入更多新的字符。目前最新的版本为2019年5月公布的12.1.0[2],已经收录超过13万个字符(第十万个字符在2005年获采纳)。Unicode涵盖的资料除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母。引用至《维基百科

为什么有这篇文章

当然是掉坑里头了。前两天做了一个表单,姓名一栏只允许填入中文。

name.value.replace(/[^\u4e00-\u9fa5]/g, '')

代码提测,本着我的代码不可能会有bug的态度下班了。晚上钉钉一阵一阵的的响。测试老哥说:哥,有bug。 我心里想:有bug?开什么玩笑,你是不是不会用?问他:哪bug了? 姓名一栏可以输入中文。 我差点发火,这不是质疑我的代码了吗。刚要反驳不可能。 测试老哥顺手丢过来两字:龿龿 说:你自己试试。

'龿龿'.replace(/[\u4e00-\u9fa5]/g, '')  //"龿龿"

嗯,怎么匹配不到?

[\u4e00-\u9fa5]有什么用

javascript采用的是utf-16 的编码方案,就是两个字节,unicode 的表现形式就是 \uxxxx 。使用[\u4e00-\u9fa5]匹配中文,\u4e00 是unicode中第一个汉字的码点,\u9fa5 是unicode中最后一个汉字的码点。

'\u4e00' // '一'
'\u95a5' // '龥'

不过显然,最后一个码点似乎不对了。 查阅各版本unicode数据文档发现:

6.2-7.0     \u4e00 - \u9fcc
8.0-9.0     \u4e00 - \u9fd5
10.0        \u4e00 - \u9fea
11.0-12.1   \4e00 - \u9fef
13.0        \4e00 - \u9ffc
14.0-15.0   \4e00 - \u9fff

没看见 \u9fa5 从那个版本开始的,但至少8.0版本后,中文的最后一个码点移动到了 \u9fd5

更正的中文匹配方式 [\u4e00-\u9fff]

'龿龿'.replace(/[\u4e00-\u9fff]/g, '') // ''
'你会不认识这几个字龦龯龿'.replace(/[\u4e00-\u9fff]/g, '') // ''

万能的中文匹配方式 /\p{sc=Han}/gu

'龿龿'.replace(/\p{sc=Han}/gu, '') // ''
'你会不认识这几个字龦龯龿'.replace(/\p{sc=Han}/gu, '') // ''

补充

文档数据可以在unicode官网查看:

unicode官网

8.0 unicode数据文档