好的,让我们不要混淆几个概念。
UTF-8字符的第一个字节为0xf0
的长度为四个字节,这是你需要编码合法Unicode字符的最长长度。由于超过94%的Unicode范围需要第四个字节,0xf0
不能映射到任何单个代码页,当然也不能映射到专用使用区域。
这些字符确实在基本多文种平面之外。但这与无效或专用使用不同;它只意味着它们的代码点大于U+FFFF(十进制值为65,535)。
如果您想排除BMP之外的所有字符,则应搜索与此正则表达式匹配的字符:
[\x{10000}-\x{10FFFF}]
这使用了Perl的\x{
...}
插值语法,通过十六进制编码来包含字符。如果你真正使用的是Perl,为了使用方便,你可能想把正则表达式放入一个变量中(使用引用正则表达式的结构qr(
...)
,因为裸斜杠会立即在赋值时尝试将正则表达式与$_
进行匹配):
my $not_bmp = qr([\x{10000}-\x{10FFFF}]);
但是,再次强调,删除与该正则表达式匹配的字符会消除超过94%的可能的Unicode字符,因此请确保您想要这样做。
如果您真的只想消除专用使用字符-其中一些在BMP内部-请特别排除这些范围。对于Perl、Python或任何其他UTF-8感知的语言,您不必担心字节;只需检查代码点即可。
如维基百科所述,三个专用使用区域位于以下代码点范围内:
- U+E000..U+F8FF
- U+F0000..U+FFFFF
- U+100000..U+10FFFF
因此,相应的Perl正则表达式如下:
my $pua = qr([\x{e000}-\x{f8ff}\x{f0000}-\x{fffff}\x{100000}-\x{10ffff}])
许多其他编程语言也有类似的Unicode支持(匹配UTF-8字符,通过代码点包含字符串中的字符等)。例如,这里是Ruby的示例,主要区别在于使用
\u{...}
代替
\x{...}
进行插值:
not_bmp = %r([\u{10000}-\u{10FFFF}])
pua = %r([\u{e000}-\u{f8ff}\u{f0000}-\u{fffff}\u{100000}-\u{10ffff}])
Python \u
转义只能使用四位十六进制数字,但如果你使用的是 Python3 或者编译成 wide 模式的 Python2,你可以使用大写的 \U
,它需要使用八位数字(不像 Perl 和 Ruby 那样支持变长的 {
...}
):
not_bmp = re.compile(u'[\U00010000-\U0010ffff]')
pua = re.compile(u'[\ue000-\uf8ff\U000f0000-\U000fffff\U00100000-\U0010ffff]')