\u 之后紧跟十六进制值 00e9(这里不区分大小写,即00E9也可以)。00e9对应十进制值233,在 ASCII 范围(0~127)之外。注意在图中字母 é(小写e加上一个重音符)被标亮了。这是因为在 Unicode 中 é 就是代码点 U+00E9,所以就被 \u00e9 匹配。
在MySQL中匹配的结果如下:
下面是一段日本诗人松尾芭蕉(Matsuo Basho,他恰巧是在伏尔泰出生的前一周去世的)的俳句。
用正则表达式 \u6c60 匹配,这是“池”字所对应的日文字符的代码点。该字会被标亮,如下图所示。
在MySQL中可以查询任意Unicode字符的代码点。
UCS2(Universal Multiple-Octet Coded Character Set)是一种使用两个字节(16位)表示 Unicode 字符集的编码方式,它能够表示 Unicode 字符集中的所有字符。
也可以从 Unicode 代码点反查字符:
需求是在 MySQL 表中查询出所有包含 emoji 符号的数据。
emoji 符号以 UTF-16 方式实现储存。以 Unicode 1F43B 为例,存储的代码点为\ud83d\udc3b。计算过程如下:
这样就得到了高低位。MySQL 实现如下:
通过对 Unicode 范围的计算,emoji 对应的编码区间用正则表达表示为:
因此可以通过类似下面的查询找出所有包含emoji符号的数据:
注意这个正则表达式不是严格匹配,其区间范围是 emoji 符号编码范围的超集,也就是说除覆盖现有全部 emoji 符号还存在空的代码点。该正则表达式可以满足目前 emoji 符号不断扩充的需求。
需求是在MySQL表中查询出所有包含中文(包括标点符号)的数据。
中文对应的编码区间用正则表达表示为:
因此可以通过类似下面的查询找出所有包含中文的数据:
注意这个正则表达式不是严格匹配,其区间范围是中文编码范围的超集,也存在空代码点。正则表达式是从左向右进行匹配的,大多数情况下,最左边两万汉字已可以完成匹配比较。
这里的实现与正则表达式无关。在后面会说明为什么加此一节。
需求是将字符串中的汉字转为拼音。创建一个汉字转拼音的函数,在其中判断每个字符是否为中文,如果是则查询拼音表取得对应的拼音,否则原样返回。网上的大部分 MySQL 转拼音函数都是通过创建一个拼音对照表,然后在自定义函数中查询该表实现的。以下对这种实现做了修改,具有以下特点:
列举这个函数的原因是,我原本打算用 regexp_replace 函数,在第三个参数中引用捕获分组的方式一次性完成替换逻辑,但未能如愿,因为函数是在正则表达式匹配之前执行(后面会看到有例外)。如下所示,upper 函数先于正则表达式执行,将参数中的常量字符变成大写,然后捕获组 $1 才会原样输出。
可以用 \w+ 匹配英语单词,然后用在循环用 regexp_substr 依次取单词,并将单词首字母转大写,单词其他字母转小写,非单词字符原样返回。
需求是这样的,将单词首字母转大写,其他字母转小写,但以点号 . 结尾的单词不做转换。先看实现:
最外层的 regexp_replace 将匹配 char(0)加上任意单一字符的标识字符串替换掉,剩下的就是符合要求的结果。
还可以使用八进制数来匹配字符,八进制数以 8 为基数,使用数字 0到7 计数。在正则表达式处理器中,就是要在反斜线(\)后加三位数字。比如,以下八进制数:\351,等同于:\u00e9。
在 MySQL 中,八进制的表示需要在数字前添加 0。
每一个 Unicode 字符,除了有 Code Point (代码点)与之对应外,还具体其他属性。在正则表达式中常用到三种 Unicode 属性:Unicode Property、Unicode Block、Unicode Script,分别对应字符功能、所属代码区段、书写系统;它们的表现形式都类似 \p{property}。
Unicode Property 的记法类似 \p{L}、\p{P}。它按照字符的功能分类 Unicode 字符,每个 Unicode 字符只能属于一个 Unicode Property。可以这样理解 Unicode Property:它并不关心字符所属的语言,只关心字符的功能,比如 \p{Z} 表示任意的空白字符或不可见的分隔符;\p{P} 表示任意标点字符,等等。遇到中英文混排、全角、半角字符同时出现的情况,看可以用 \p{Z} 匹配所有的空白字符(而不用关心空格到底是全角空格还是半角空格),用 \p{P} 匹配所有的标点字符(而不用关心逗号到底是中文逗号还是英文逗号)。
如果把 Unicode Property 理解为一个“字符组”,一定还有对应的排除型字符组,此排除型字符组的通行记法是将 \p{property} 中的小写改为大写 P,写作 \P{property}。
不同于 Unicoe Property,Unicode Block 按照编码区间划分 Unicode 字符,各个区间彼此联系但互不相交,所以每个 Unicode 编码中的每个字符都有唯一归属的 Unicode Block。
在 Unicode 编码表中,同一种语言的字符通常落在同一区间的,所以 Unicode Block 也可以粗略表示某类语言的字符,比如 \p{InHebrew} 表示希伯莱语字符,\p{InCJK_Unified_Ideographs} 表示兼容 CJK(中文、日文、韩文)统一表意字符。Unicode Block 的名字都有 In(Java风格)或者 Is(.NET风格)前缀,所以它对应的还是“落在某个区间的 Unicode 字符”。
另外值得一用的是 \p{InCJK_Symbols_and_Punctuation},从命名上来看,它覆盖了中文、日文、韩文中的大部分常见标点,但事实并非如此。比如全角逗号和叹号不匹配此属性,而全角句号就匹配。不过,所有标点都在 \p{P} 这个 Unicode Property 中。
Unicode Script 按照字符所属的书写系统来划分 Unicode 字符,比如 \p{Greek} 表示希腊语字符,\p{Han} 表示汉语(中文字符)。它的写法类似 Unicode Block,只是名字的开头没有 Is 或者 In。可以很方便地用 \p{Han} 来匹配中文字符。
很少会在文本中查找控制字符,但知道如何做也不是件坏事。在正则表达式中,可以像这样来指定一个控制字符:\cx ,其中 x 就是想匹配的控制字符。
如果没有括号,\b 会被认为是单词边界。括号改变了正则表达式处理器对 \b 的理解方式。