PHP中的正则表达式元字符\w和\pL

4

在版本5.3.4 - 5.5.0beta1中,\w\pL是否等价?


 <?php
preg_match_all('#\w#u','سیب',$f);
var_dump($f);

preg_match_all('#\pL#u','سیب',$f);
var_dump($f);

array(1) {
  [0]=>
  array(3) {
    [0]=>
    string(2) "س"
    [1]=>
    string(2) "ی"
    [2]=>
    string(2) "ب"
  }
}
array(1) {
  [0]=>
  array(3) {
    [0]=>
    string(2) "س"
    [1]=>
    string(2) "ی"
    [2]=>
    string(2) "ب"
  }
}

Try the above snippet in the Online PHP shell

1个回答

9
当您在PCRE正则表达式中使用u修饰符时,似乎PHP除了设置PCRE_UTF8标志外,还设置了PCRE_UCP标志,这会导致Unicode属性被引入到\w和其他POSIX字符类中,而不仅仅是默认的ASCII字符。来自PCRE手册页面的内容如下:

PCRE_UCP

此选项更改PCRE处理\B、\b、\D、\d、\S、\s、\W、\w和某些POSIX字符类的方式。默认情况下,只识别ASCII字符,但如果设置了PCRE_UCP,则使用Unicode属性来对字符进行分类。

然后在PHP源代码中确认了这一点(第366-372行),我们可以看到以下内容:
        case 'u':   coptions |= PCRE_UTF8;
/* In  PCRE,  by  default, \d, \D, \s, \S, \w, and \W recognize only ASCII
   characters, even in UTF-8 mode. However, this can be changed by setting
   the PCRE_UCP option. */
#ifdef PCRE_UCP
                    coptions |= PCRE_UCP;
#endif

因此,从我上面链接的同一手册中,您会看到当设置PCRE_UCP时,字符类变为:

\d 与\p{Nd}匹配的任何字符(十进制数字)

\s 与\p{Z}匹配的任何字符,加上HT、LF、FF、CR

\w 与\p{L}或\p{N}匹配的任何字符,加上下划线


完美的答案。在 PHP 中打开 u 标志就像在正则表达式前面添加 (*UCP)(*UTF8) 一样。不幸的是,截至 PCRE 8.34,没有办法在内联中关闭 PCRE_UCP。我说“不幸”,因为这使得 \w 运行变慢,根据 PCRE 手册:“通过 Unicode 属性匹配字符并不快,因为 PCRE 必须进行多级表查找才能找到字符的属性。这就是为什么默认情况下,传统的转义序列(如 \d 和 \w)在 PCRE 中不使用 Unicode 属性,尽管您可以通过设置 PCRE_UCP 选项或以 (*UCP) 开始模式来使它们这样做。” - zx81
实际上,有一种解决方法可以使用UTF8而不需要UCP:内联设置UTF8,而不是使用u标志。例如:"(*UTF8)\w+" 这确保了Unicode模式已打开,但\w不匹配\p{L}。 - zx81

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