为什么PHP preg_match_all与PCRE_UTF8在CLI上和通过Apache/mod_PHP提供不同的结果?
以下代码在通过CLI和Apache/mod_php运行时会产生不同的结果:为什么PHP preg_match_all与PCRE_UTF8在CLI上和通过Apache/mod_PHP提供不同的结果?,php,utf-8,preg-match-all,pcre,Php,Utf 8,Preg Match All,Pcre,以下代码在通过CLI和Apache/mod_php运行时会产生不同的结果: <pre> <?php error_reporting(E_ALL); ini_set('display_errors', '1'); echo setlocale(LC_ALL, 0)."\n"; // echo setlocale(LC_ALL, "en_GB.UTF-8")."\n"; $terms = array ( //Always matches: "Label Gene
<pre>
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
echo setlocale(LC_ALL, 0)."\n";
// echo setlocale(LC_ALL, "en_GB.UTF-8")."\n";
$terms = array
(
//Always matches:
"Label Generation",
//Doesn't match when using u (PCRE_UTF8) modifier:
"Receipt of Prescription and Validation of Patient Information",
);
$text = "Some terms to match: ".implode(", ",$terms);
$pattern = "/(".implode(")|(", $terms).")/is";
$regexps = array
(
"Unicode" => $pattern."u", //Add u (PCRE_UTF8) modifier
"Non-unicode" => $pattern
);
echo "Text:\n'$text'\n";
foreach($regexps as $type=>$regexp)
{
$matches = array();
$total = preg_match_all($regexp,$text,$matches);
echo "\n\n";
echo "$type regex:\n'$regexp'\n\n";
echo "Total $type matches: ";
var_dump($total);
echo "\n$type matches: ";
var_dump($matches[0]);
}
?>
</pre>
/en_GB.ISO8859-1/C/C/C/C/C
Text:
'Some terms to match: Label Generation, Receipt of Prescription and Validation of Patient Information'
Unicode regex:
'/(Label Generation)|(Receipt of Prescription and Validation of Patient Information)/isu'
Total Unicode matches: int(1)
Unicode matches: array(1) {
[0]=>
string(16) "Label Generation"
}
Non-unicode regex:
'/(Label Generation)|(Receipt of Prescription and Validation of Patient Information)/is'
Total Non-unicode matches: int(2)
Non-unicode matches: array(2) {
[0]=>
string(16) "Label Generation"
[1]=>
string(61) "Receipt of Prescription and Validation of Patient Information"
}
使用/u(PCRE\u UTF8)选项时,web服务器无法匹配两个字符串。
我试过setlocale(LC_ALL,“en_GB.UTF-8”)
将web服务器区域设置与CLI区域设置相匹配,该区域设置已成功匹配,但与输出无关。
我怀疑PCRE库有问题,但我不明白CLI和web服务器之间有什么不同-PHP在两种环境中报告相同的库版本:
PHP 5.4.14
PCRE(与Perl兼容的正则表达式)支持=>已启用
PCRE库版本=>8.32 2012-11-30
pcretest报告不支持UTF-8,但尽管如此,CLI版本仍能产生正确的结果
/opt/pcre/bin/pcretest -C
一些Linux发行版(以Ubuntu为例)将其PHP打包为CLI和Apache的单独PHP.ini文件。如果这是你的情况,那么你可能需要在/etc/php5中探索并研究差异。阿拉斯泰尔,发掘这个古老的问题,因为它涉及到各个时代编码人员感兴趣的永恒问题 正如迪诺所说,在同一个盒子上有几个版本的PCRE是很常见的。我总是惊讶于平均cPanel构建中安装了多少版本的PCRE。这可能不是您的情况,但您似乎也有多个版本 要查看安装了哪些PCRE,请在unix shell中键入: 如果你想得到一些有意义的信息,你会想使用你一直在做的pcretest,这样你就可以
find/-name pcretest
然后somepath/pcretest-C
如果您使用的是cPanel,EasyApache安装的PCRE版本就是opt/
文件夹中的版本。您可以通过运行
这是一片混乱,但这让我们保持警觉 这个PHP设置帮助了我:
pcre.jit=0
您的问题有点暗示您已经检查了这一点,但只是再次检查-您是否比较了两个环境中的phpinfo()
/php-i
,以确保它们都使用相同的php和PCRE版本?另外,测试源文件的编码是什么?@DaveRandom:是的,双方都同意PHP和PCRE版本(分别为5.4.14和8.32 2012-11-30)。升华文本报告文件编码为UTF-8。此外,它与通过CLI和web服务器运行的文件完全相同,即只有一个文件。这可能是Apache的错误。闻起来很相似,这意味着mod_php继承了Apache PCRE,这听起来有点古怪…:-SAlas,在这种情况下,他们使用的是相同的php.inith当preg_匹配在命令行上工作时,这也是我的解决方案,但不是通过mod_php。PCRE编译最近更改为添加JIT支持,php默认启用JIT(如果可用)。CLI版本使用了不同的PCRE。
$> pcretest -C
PCRE version 8.32 2012-11-30
Compiled with
8-bit support
No UTF-8 support
No Unicode properties support
No just-in-time compiler support
Newline sequence is LF
\R matches all Unicode newlines
Internal link size = 2
POSIX malloc threshold = 10
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack
find / -name libpcre.*
/opt/pcre/bin/pcretest -C