【问题标题】:Does \w match all alphanumeric characters defined in the Unicode standard?\w 是否匹配 Unicode 标准中定义的所有字母数字字符?
【发布时间】:2011-07-30 03:53:54
【问题描述】:

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+$/);
}

【问题讨论】:

    标签: regex perl unicode internationalization character-properties


    【解决方案1】:

    perldoc perlunicode

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

    所以看起来你的问题的答案是“是”。

    但是,您可能希望使用\p{} 构造直接访问特定的Unicode character properties。您可能可以使用\p{L}(或更短的\pL)来表示字母,使用\pN 来表示数字,这样您就会更有信心得到您想要的。

    【讨论】:

    • 请注意,这取决于字符语义;如果您的字符串来自使用字节语义的源,\w 将仅匹配 ASCII 单词字符。
    • 有关 Unicode 字符语义的更多详细信息,请参阅The Unicode Bug in perlunicode。与\w 等效的保险箱是使用\p{Alnum}
    • @cjm, \w 实际上是\p{Word}\p{Alnum} 缺少下划线。
    • @Anomie:还有语言环境问题。
    • @CanSpice:“字母”!=“字母”。您绝不能使用\pL 来表示\p{Alphabetic}。他们真的很不一样。从 Unicode 6 开始,有 1006 个代码点具有 Alphabetic 属性但缺少 GC=Letter 属性。
    【解决方案2】:

    是和不是。

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

    因为与大多数正则表达式系统不同,Perl 遵守 Requirement 1.2a, “Compatibility Properties” 来自 UTS #18 on Unicode Regular Expressions,然后 假设您有 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,SUPERSCRIPT TWO,只有 \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 不一样,这有什么意义?莫名其妙。
    【解决方案3】:

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

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

    下划线是单词字符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 2012-06-02
      • 2011-08-25
      • 2012-04-23
      • 2012-04-16
      • 1970-01-01
      • 2015-04-21
      相关资源
      最近更新 更多