编译失败:不支持POSIX整理元素

时间:2011-08-24 10:14:51

标签: php regex posix preg-match pcre

我刚刚安装了一个网站&遗留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?

先谢谢,我的伏都教不够强壮;)

2 个答案:

答案 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字符类

在一个方形括号内的字符类中,POSIX允许三种不同的嵌套括号内的表单,所有表示都使用括号内的额外符号成对:

  1. 命名的POSIX字符类,基本上类似于Unicode属性,在[:PROPERTY:]中使用额外的冒号:[:alpha:]
  2. 整理要被视为彼此等同的元素,在其侧翼使用额外的等号:[=ELEMENTS=],如英语或法语中的[=eéèëê=],以及瑞典语中的[=vw=]
  3. 多重图(有向图,三字图,四图等),它们是多字符元素,可以算作单个字符,在它们的侧翼有一个额外的点:[.DIGRAPH.],如[.ch.]或{{1按照传统的西班牙语字母表。这些有时被称为收缩,因为两个或多个代码点被计算为该序列是单个代码点。
  4. 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íaniño llave choco 等字词匹配;或者用德语

    [$ES]{4}
    

    并将其匹配为tschüß或其大写未命名的等效词, TSCHUESS

    Unicode方式

    由于各种原因,这很尴尬,而不仅仅是上面列出的两个字母表中显而易见的那些原因。它不承认组合字符的概念,因此您必须明确地为非规范化文本添加这些字符,如[$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. ICU的Collation Concepts文件
    2. UTS#10: Unicode Collation Algorithm
    3. Perl的Unicode::Collate模块。
    4. Perl的Unicode::Collate::Locale模块。

答案 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