【问题标题】:Strange PHP UTF-8 Behaviour奇怪的 PHP UTF-8 行为
【发布时间】:2010-11-11 11:53:28
【问题描述】:

我有以下测试PHP代码:

header('Content-type: text/html; charset=utf-8');

$text = 'Développeur Web';
var_dump($text);

$text = preg_replace('#[^\\pL\d]+#u', '-', $text);
var_dump($text);

$text = trim($text, '-');
var_dump($text);

$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
var_dump($text);

$text = strtolower($text);
var_dump($text);

$text = preg_replace('#[^-\w]+#', '', $text);
var_dump($text);

在我的本地机器上它按预期工作:

string(16) "Développeur Web" 
string(16) "Développeur-Web" 
string(16) "Développeur-Web" 
string(16) "D'eveloppeur-Web" 
string(16) "d'eveloppeur-web" 
string(15) "developpeur-web" 

但在我的实时服务器上,它的行为很奇怪:

string 'Développeur Web' (length=16)
string '-pp-' (length=4)
string 'pp' (length=2)
string 'pp' (length=2)
string 'pp' (length=2)
string 'pp' (length=2)

本地机器是运行 PHP 版本 5.2.4 的 Windows,而实时服务器是运行 PHP 版本 5.2.10 的 CentOS,因此它们无论如何都不相同,我知道并不理想。

有没有人经历过类似的事情并且可以为我指明正确的方向?我假设它是某种与 UTF-8 或语言环境相关的服务器或 PHP 配置。

在此先感谢

【问题讨论】:

  • 奇怪。我不擅长正则表达式 - 你能详细说明第一个 preg_replace() 正在做什么吗?
  • 我最初想到的是mb_default_encoding(),但该库与preg_* 函数无关。
  • 第一个正则表达式应该用“-”替换非字母或数字,它来自 Symfony 教程symfony-project.org/jobeet/1_4/Doctrine/en/08
  • @Pekka:我认为正则表达式旨在用- 替换不是数字或不是Unicode 属性L 的字符(即Letter)的每个字符.见de2.php.net/manual/en/regexp.reference.unicode.php
  • @Stefan 干杯!那是我缺少的部分。在这种情况下,值得检查是否如手册所述,PCRE is compiled with "--enable-unicode-properties"(如果不是,则应该有错误消息)。

标签: php linux apache utf-8 preg-replace


【解决方案1】:

不应该

$text = preg_replace('#[^\pL\d]+#u', '-', $text);

在第 6 行。如果您转义 \,您的排除类中将有一个文字 \。因此,正则表达式[^\\pL\d]+ 会找到一个或多个不是\pL 或数字的字符。这可以解释为什么"Développeur Web" 将减少为"-pp-" - 直到第一个p 匹配并将被- 替换;第二个p 之后的所有内容也是如此。

也许两台机器在处理转义的\ 方面存在差异。

EDIT OP 评论后:

实际上转义 \ 在这里没有问题 - 两个版本的处理方式相同。实际上似乎是问题所在,使用的 PCRE 版本不支持 unicode 属性并且没有使用 --enable-unicode-properties 编译。

【讨论】:

  • 我已经按照你的建议替换了模式,但我仍然没有得到想要的结果。
  • 我自己一直在研究它,并认为它可能与 PCRE 有关.. 现在仍在寻找。
  • pcretest -C PCRE 版本 6.6 06-Feb-2006 编译时支持 UTF-8 不支持 Unicode 属性 换行符为 LF 内部链接大小 = 2 POSIX malloc 阈值 = 10 默认匹配限制 = 10000000 默认递归深度限制 = 10000000 匹配递归使用堆栈
  • 您能否验证 PCRE 是在您的实时系统上使用 --enable-unicode-properties 构建的?
  • 不支持 Unicode 属性 似乎是问题的根源。由于缺少支持,正则表达式 '#[^\\pL\d]+#u' 实际上将按照我上面写的方式处理 - 它无法识别 \pL 的特殊含义。
猜你喜欢
  • 2011-04-08
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2011-04-14
相关资源
最近更新 更多