\w是否匹配Unicode标准中定义的所有字母数字字符?

24

Perl的\w是否匹配Unicode标准中定义的所有字母数字字符?

例如,\w是否匹配所有(比如说)中文和俄语字母数字字符?

我编写了一个简单的测试脚本(见下文),表明\w确实符合我测试过的非ASCII字母数字字符的预期匹配。但是测试显然远非全面。

#!/usr/bin/perl                                                                                                                                                                                                  

use utf8;

binmode(STDOUT, ':utf8');

my @ok;
$ok[0] = "abcdefghijklmnopqrstuvwxyz";
$ok[1] = "éèëáàåäöčśžłíżńęøáýąóæšćôı";
$ok[2] = "şźüęłâi̇ółńśłŕíáυσνχατςęςη";
$ok[3] = "τσιαιγολοχβςανنيرحبالтераб";
$ok[4] = "иневоаслкłјиневоцедањеволс";
$ok[5] = "рглсывызтоμςόκιναςόγο";

foreach my $ok (@ok) {
    die unless ($ok =~ /^\w+$/);
}
3个回答

22

perldoc perlunicode 表示:

正则表达式中的字符类是用于匹配字符而不是字节,并根据 Unicode 属性数据库中指定的字符属性进行匹配。例如,可以使用\w来匹配日语汉字。

因此看起来对你的问题的答案是“是”。

但是,您可能希望使用\p{}结构直接访问特定的Unicode字符属性。您可以使用\p{L}(或更短的\pL)表示字母和使用\pN表示数字,并且可以更有把握地获取确切的匹配内容。


4
请注意,这取决于字符语义;如果您的字符串来自使用字节语义的源,则 \w 仅匹配 ASCII 单词字符。 - Anomie
3
有关Unicode字符语义的更多详细信息,请参见perlunicode中的Unicode错误\w的安全等效项是使用\p{Alnum} - cjm
2
@cjm,\w 其实是 \p{Word}\p{Alnum} 缺少下划线。 - ikegami
@Anomie:还有本地化问题。 - tchrist
1
@CanSpice: "Letter" != "Alphabetic". 您绝不能使用\pL来表示\p{Alphabetic}。它们实际上是非常不同的。自Unicode 6以来,有1006个代码点具有字母属性但缺少GC = Letter属性。 - tchrist

12

是和不是。

如果您想要所有字母数字,则需要 [\ p {Alphabetic} \ p {GC = Number}] \ w 包含比这更多和更少。 它特别排除任何不是 \ p {Nd} \ p {Nl} \ pN ,例如上标,下标和分数。 那些是 \ p {GC = Other_Number} ,不包括在 \ w 中。

因为与大多数正则表达式系统不同,Perl遵守UTS#18关于Unicode正则表达式Requirement 1.2a,“Compatibility Properties”,所以假设您有Unicode字符串,则正则表达式中的 \ w 匹配具有以下四个属性之一的任何单个代码点:

  1. \ p {GC = Alphabetic}
  2. \ p {GC = Mark}
  3. \ p {GC = Connector_Punctuation}
  4. \ p {GC = Decimal_Number}

上述第4点可以用以下任何一种方式表示,这些都被视为等效:

  • \p{Digit}
  • \p{General_Category=Decimal_Number}
  • \p{GC=Decimal_Number}
  • \p{Decimal_Number}
  • \p{Nd}
  • \p{Numeric_Type=Decimal}
  • \p{Nt=De}

请注意,\p{Digit}\p{Numeric_Type=Digit}不同。例如,代码点B2,上标二,仅具有\p{Numeric_Type=Digit}属性,而没有纯粹的\p{Digit}。这是因为它被认为是\p{Other_Number}\p{No}。但是,正如您想象的那样,它确实具有\p{Numeric_Value=2}属性。

上面的第1个要点\p{Alphabetic}真正让人们感到困扰。这是因为他们太容易错误地认为它与\p{Letter}(\pL)相同,但实际上并不是。

Alphabetics不仅仅包括字母,这是因为\p{Other_Alphabetic}属性的存在,它又包括一些但不是全部的\p{GC=Mark},全部的\p{Lowercase}(它与\p{GC=Ll}不同,因为它添加了\p{Other_Lowercase})以及全部的\p{Uppercase}(它与\p{GC=Lu}不同,因为它添加了\p{Other_Uppercase})。
这就是它如何引入\p{GC=Letter_Number},例如罗马数字,以及所有圆形字母,它们属于\p{Other_Symbol}和\p{Block=Enclosed_Alphanumerics}类型。
你难道不高兴我们可以使用\w吗? :)

“其他字母”包括GC=Mark是有道理的吗?“小写字母”为什么不等同于GC=Ll?令人困惑。 - Cheeso

2

特别地,\w 也匹配下划线字符。

#!/usr/bin/perl -w
$name = 'Arun_Kumar';
($name =~ /\w+/)? print "Underscore is a word character\n": print "No underscores\n";
$ underscore.pl 

下划线是一个单词字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接