我刚刚安装了一个网站&遗留CMS到我们的服务器上,我收到POSIX编译错误。幸运的是它只出现在后端,但是客户热衷于摆脱它。
Warning: preg_match_all() [function.preg-match-all]: Compilation failed:
POSIX collating elements are not supported at offset 32 in
/home/kwecars/public_html/webEdition/we/include/we_classes/SEEM/we_SEEM.class.php
on line 621
据我所知,这是导致问题的新版PHP。这是代码:
function getAllHrefs($code){
$trenner = "[\040|\n|\t|\r]*";
$pattern = "/<(a".$trenner."[^>]+href".$trenner."[=\"|=\'|=\\\\|=]*".$trenner.")
([^\'\">\040? \\\]*)([^\"\' \040\\\\>]*)(".$trenner."[^>]*)>/sie";
preg_match_all($pattern, $code, $allLinks); // ---- line 621
return $allLinks;
}
如何调整此功能以在此服务器上运行较新版本的php?
先谢谢,我的伏都教不够强壮;)
答案 0 :(得分:22)
“不支持POSIX整理元素”的错误消息值得一些解释。毕竟,无论如何,世界上还有POSIX整理元素,我该如何避免呢?
简短的回答是,你在方括号内有一个等号,它的用途是为了将来使用而保留,假设我们总是要实现它,这是不确定的。您可以通过这种方式在命令行中使用Perl来解决这个问题,这样可以提供比PHP提供的更好的错误消息:
% perl -le 'print "abc" =~ /[=foo=]/ || "Fail"'
POSIX syntax [= =] is reserved for future extensions in regex; marked by <-- HERE in m/[=foo=] <-- HERE / at -e line 1.
这是简短的答案;更长的答案如下。
在一个方形括号内的字符类中,POSIX允许三种不同的嵌套括号内的表单,所有表示都使用括号内的额外符号成对:
[:PROPERTY:]
中使用额外的冒号:[:alpha:]
。[=ELEMENTS=]
,如英语或法语中的[=eéèëê=]
,以及瑞典语中的[=vw=]
。 [.DIGRAPH.]
,如[.ch.]
或{{1按照传统的西班牙语字母表。这些有时被称为收缩,因为两个或多个代码点被计算为该序列是单个代码点。Perl仅支持其中的第一个,而不支持第二个和第三个。
它们都很难使用,因为它们必须嵌套在一组额外的括号中,如[.ll.]
中的[[:punct:]
或\pP
。当您选择其中一个时,您只需要具有Unicode属性的额外大括号,如\p{punct}
。
另外两个是尝试在传统的8位语言环境下支持Unicode前环境中的特定于语言环境的语言元素。例如,要表达传统的西班牙语字母表,它将 u 上的元音和diaereses上的急性重音计为同一个字母,但它在 n 上计算了一个波浪号。完全不同的字母,还有两个有效字母,每个字母都算作一个独特的字母,你必须在POSIX中写这个:
[\pL\pN\pM\p{Pc}]
你可以并且有时将这些结合起来。例如,在德语电话簿中,通过插入以下 e ,三个 i - 突变的元音可以拼写而没有变音符号:
[[=aá=]bc[.ch.]d[=eé=]fgh[=ií=]jkl[.ll.]mnñ[=oó=]pqrst[=uúü=]vwxyz]
这样,假设[a[=ä[.ae.]=]bcdefghijklmno[=ö[.oe.]=]pqrs[=ß[.ss.]=]tu[=ü[.ue.]=]vwxyz]
和$ES
是这些语言的各自字母,您可以说类似
$DE
并将其与西班牙语中的guía,niño, llave 和 choco 等字词匹配;或者用德语
[$ES]{4}
并将其匹配为tschüß或其大写未命名的等效词, TSCHUESS 。
由于各种原因,这很尴尬,而不仅仅是上面列出的两个字母表中显而易见的那些原因。它不承认组合字符的概念,因此您必须明确地为非规范化文本添加这些字符,如[$DE]{6}
。
Unicode在如何实现这样的语言元素方面走了另一条道路。幸运的是,在Unicode regular expressions per UTS#18之前,Level 3不需要支持为特定语言或区域设置定制的语言功能。这还没有人实施过。
请注意,让 SS 和ß具有相同的casefold不被视为区域设置剪裁。无论语言环境如何,它都是该代码点的完整案例折叠。因此,当忽略大小写时,这些是相同的。奇怪但真实。鉴于ß是代码点U + 00DF,我们看到无论区域设置如何都是相同的:
[=e\xE9[.e\x{301.]=]
虽然模式的区域设置定制仍然超出我们的范围,但是已经实现了排序规则,包括区域设置支持,您可以从Perl中访问它。
但是,PHP尚不支持Unicode排序规则。
Unicode排序规则的参考包括:
答案 1 :(得分:4)
[...]
是字符类,它们匹配括号中的任何字符,您不必在它们之间添加|
。请参阅character classes。
因此[abcd]
将匹配a or b or c or d
。
如果要匹配多个字符的替换,例如red or blue or yellow
,请使用子模式:
"(red|blue|yellow)"
你猜对了,[abcd]
相当于(a|b|c|d)
。
所以这就是你可以为正则表达式做的事情:
对于
$trenner = "[\040|\n|\t|\r]*";
改为写下:
$trenner = "[\040\n\t\r]*";
而
"[=\"|=\'|=\\\\|=]"
你可以做到
"(=\"|=\'|=\\\\|=)"
或者
"=[\"'\\\\]?"
顺便说一句,您可以使用\s
代替$trenner
(请参阅http://www.php.net/manual/en/regexp.reference.escape.php)