正则表达式 Unicode 编码模式中的点号匹配问题
很多时候我们在构造正则表达式时不会考虑编码的问题,因为默认的 ASCII 编码已经足够我们应对大多数开发场景,但这并不代表对编码的需求就不存在,典型的例子就是用户注册时,要求用户名一定要是中文的情况,这种情况下 ASCII 编码就无能为力了。现在轮到 Unicode 这砣灵丹妙药出场了。
通常情况下我们都认为一个字符就对应到一个 Unicode 代码点,即一一对应的关系。但这里存在理解上的偏差,一般人所谓的单个字符在 Unicode 编码中可能并不和单个代码点对应而是由多个代码点组合而成。比如 å 这种带声调修饰的单个字符在 Unicode 编码中就是由 \u0061 和 \u030A 这两个代码点组合而成。这就又给我们带来了新的问题,正则表达式的点号元字符在匹配这样的由多个代码点组合而成的字符时,是匹配一个代码点映射的单字符还是匹配多个代码点合成后映射到的单字符?
my $str = “å”;
$str =~ m/(.)/;
print “normal: $1\n”;
$str =~ m/(\X.)/;
print “\\X mode: $1\n\n”;
上面代码输出效果如下:
可以看到要想正确的匹配 å 单字,必须通过 \X 来显示通知正则引擎“匹配一个 Unicode 代码点组合”。不幸的是并不是所有编程语言的正则表达式引擎都实现了 \X 模式。(所以到目前为止,在字符处理方面 Perl/PCRE 还是当之无愧的王者啊!)

你的å是怎么打出来的啊?我又火星了哇
hkbarton
24 May 09 at 3:52 am
网上有 Unicode 的编码表,直接复制嘛。不过其实我更火星,我先在 django Views 里面给一个变量赋值
str = u’\u0061\u030a’
然后再把这个值传到传到网页里呈现,拼着我再从页面里把这个 å 复制到 Perl 程序里面…
火星怕啥嘛,我还冥王星嘞…
admin
24 May 09 at 6:47 am
厄, 冥王星…你跟我学…
hkbarton
25 May 09 at 8:51 am
从来玩不来正则的人飘过…… T_T
小适
25 May 09 at 9:04 am
恩 背景好看……
uk
26 May 09 at 9:07 am