正则表达式——码值

  Unicode 字符多种多样,除去 ASCII 中的字母、数字、标点和中文字符,还包括其他多种语言和多种符号,有些符号甚至很难打出来(比如表示商标注册的™️),这时候该如何表示呢?再说远一点,如果我们想用一个字符组匹配所有的中文字符,能不能像[a-z]那样呢?

  使用正则表达式解决这类问题,必须依赖码值。前面讲过,每一个 Unicode 字符都有一个 Unicode 码值,所以在正则表达式的 Unicode 字符往往采用 Unicode 码值来指定。

  一般来说,指定码值的形式有两种:\uxxxx和\u{xxxx}(其中的 xxxx 为编码的值,\u之后必须有4位十六进制数字)。.NET、Java、JavaScript 和 Python 使用前一种形式,而 PHP 和 Ruby 使用后一种形式(Ruby 1.9 以上版本才支持这种表示法,PHP 使用的字母是 x 而不是 u:\x{xxxx})

  比如“发表”的“发”字对应的 Unicode 编码是 53 d1,所以可以在.NET、Java、JavaScript 的正则表达式中用\u53d1 表示它;Python 稍有不同,必须使用 u"\u53d1"(之前的 u 表示这是一个 Unicode 字符串);在 Ruby 中必须写作\u{53d1};在 PHP 中则写作\x{53d1}。

编码 语言 表示法 说明
53 d1 .NET \u53d1
Java \u53d1
JavaScript \u53d1
Python \u53d1 必须使用 Unicode 字符串,在 Python 2 中,
要在字符串之前加 u 指定 Unicode 字符串
PHP \x{53d1} 必须指定 Unicode 模式
Ruby \u{53d1} 限 Ruby 1.9 以上版本,且必须显示指定
Unicode 模式

  既然可以这样指定 Unicode 字符,自然也可以在字符组中用范围表示法指定一个 Unicode 编码范围了。这个功能,最常见的应用就是匹配任意一个中文字符。查询 Unicode 编码表可知,中文字符的编码点大多位于 4e00 到 9fff 之间,所以可以用这样的字符组匹配中文字符(Unicode 编码 4e00-9fff归类为** CJK 统一表意符号** CJK Unified Ideographs,涵盖了绝大多数中文字符)。

常用语言中匹配中文字符的字符组

语言 字符组 说明
.NET [\u4e00-\u9fff]
Java [\u4e00-\u9fff]
JavaScript [\u4e00-\u9fff]
Python [\u4e00-\u9fff] 必须使用 Unicode 字符串,在Python 2 中,要在字
符串之前加 u 指定 Unicode 字符串
PHP [\x{4e00}-\x{9fff}] 必须指定 Unicode 字符串
Ruby [\u{4e00}-\u{9fff}] 限 Ruby 1.9 以上版本

  如果实在没有办法使用 Unicode 编码环境,而只能采用 GBK 编码,在 Python、Ruby 1.8 和 PHP 中,也有个办法匹配所有的中文字符;查阅 GBK 编码表可知,中文字符的 GBK 码值从 b0 00 开始,到 fa a0 结束,但是在通常情况下正则引擎无法正确识别非 Unicode 编码字符串的字符边界,所以不能写作[\xb000-\xfea0],只能写作[\xb0-\xfe][\x00-\xff],它匹配两个字节,第一个字节的码值范围从 b0 到 fe,第二个字节的码值范围从 00 到 ff,如果要匹配多个中文字符,必须添加括号将这两个字节分为一组,再使用量词,比如([\xb0-\xfe][\x00-\xff])+。因为此时完全是将字符串作为单字节序列来对待的,所以也不应该指定任何与 Unicode 有关的设置(无论是正则表达式还是字符串,都是如此)。

posted @ 2018-12-13 18:29  gaara724  阅读(941)  评论(0编辑  收藏  举报