Perl 5 中填充正则表达式量词的 Unicode 字符

Unicode characters stuffing regex quantifiers in perl 5

我是 perl 的新手,在使用 perl 5 的多字节 unicode 字符 (utf-8) 上使用正则表达式量词时遇到问题,我希望它们只计算一个字符,但它们计算组成它们的字节数。

例如,我希望 .{1} 匹配 é.{2} 不匹配,但我看到了:

$ echo 'begin é end' | perl -wnl -e '/begin .{1} end/s and print'

$ echo 'begin é end' | perl -wnl -e '/begin .{2} end/s and print'
begin é end

这显然是因为“é”是一个多字节字符,因为当我用一个简单的“e”替换它时,我得到了我期望的结果:

$ echo 'begin e end' | perl -wnl -e '/begin .{1} end/s and print'
begin e end

$ echo 'begin e end' | perl -wnl -e '/begin .{2} end/s and print'

使用一些 character set modifier(/d /u /a 和 /l)不会改变任何东西。

当我使用另一个 PCRE 正则表达式工具时,它起作用了:

$ echo 'begin é end' | php7 -r 'var_dump(preg_match("/begin .{1} end/su", file_get_contents("php://stdin")));'
Command line code:1:
int(1)

我的 TTY 使用 UTF-8 字符集,“é”被编码 c3a9 :

$ echo 'begin é end' | xxd
00000000: 6265 6769 6e20 c3a9 2065 6e64 0a         begin .. end.

$ echo 'begin é end' | base64
YmVnaW4gw6kgZW5kCg==

我已经在几个 OS 和 perl 版本上进行了测试,我发现到处都是相同的行为:

This is perl 5, version 22, subversion 1 (v5.22.1) built for i686-msys-thread-multi-64int   (Windows 7)
This is perl 5, version 26, subversion 1 (v5.26.1) built for x86_64-msys-thread-multi       (Windows 10)
This is perl 5, version 22, subversion 1 (v5.22.1) built for x86_64-linux-gnu-thread-multi  (Ubuntu 16.04)

如何使 perl 正则表达式量词将 unicode 字符计数为一个?

您需要告诉 Perl 输入是用 UTF-8 编码的。这是由 -CI 完成的。添加 O 以对输出进行编码:

echo 'begin é end' | perl -CIO -wnl -e '/begin .{1} end/s and print'
begin é end