将多个匹配正则表达式合并为一个并获得匹配的正则表达式

时间:2013-04-24 14:45:12

标签: php regex preg-match

我有一个正则表达式列表:

suresnes|suresne|surenes|surene
pommier|pommiers
^musique$
^(faq|aide)$
^(file )?loss( )?less$
paris
faq                              <<< this match twice

我的用例是每个获得匹配的模式都显示一个指向我的用户的链接, 所以我可以有多种模式匹配。

我根据一条简单的文字“巴黎生活”/“常见问题”/“pom”来测试模式...

这样做的简单方法是使用preg_match遍历所有模式,但我会在效果关键页上做很多事情,所以这对我来说很糟糕

以下是我尝试过的方法:将所有thoses表达式组合成一个组名:

preg_match("@(?P<group1>^(faq|aide|todo|paris)$)|(?P<group2>(paris)$)@im", "paris", $groups);

如您所见,每个模式都已分组:(?P<GROUPNAME>PATTERN)并且它们都由管道|分隔。

结果不是我所期望的,因为只返回第一组匹配。看起来当匹配发生时,解析就会停止。

我想要的是所有匹配组的列表。 preg_match_all也没有帮助。

谢谢!

3 个答案:

答案 0 :(得分:6)

怎么样:

preg_match("@(?=(?P<group1>^(faq|aide|todo|paris)$))(?=(?P<group2>(paris)$))@im", "paris", $groups);
print_r($groups);

<强>输出:

Array
(
    [0] => 
    [group1] => paris
    [1] => paris
    [2] => paris
    [group2] => paris
    [3] => paris
    [4] => paris
)

(?= )被称为lookahead

正则表达式的解释:

(?=                                     # start lookahead
    (?P<group1>                         # start named group group1
        ^                               # start of string
            (                           # start catpure group #1
                faq|aide|todo|paris     # match any of faq, aide, todo or paris
            )                           # end capture group #1
        $                               # end of string
    )                                   # end of named group group1
)                                       # end of lookahead
(?=                                     # start lookahead
    (?P<group2>                         # start named group group2
            (                           # start catpure group #2
            paris                       # paris
        )                               # end capture group #2
        $                               # end of string
    )                                   # end of named group group2
)                                       # end of lookahead

答案 1 :(得分:1)

尝试这种方法:

#/ define input string
$str_1 = "{STRING HERE}";

#/ Define regex array
$reg_arr = array(
'suresnes|suresne|surenes|surene',
'pommier|pommiers',
'^musique$',
'^(faq|aide)$',
'^(file )?loss( )?less$',
'paris',
'faq'
);

#/ define a callback function to process Regex array
function cb_reg($reg_t)
{
    global $str_1;
    if(preg_match("/{$reg_t}/ims", $str_1, $matches)){
    return $matches[1]; //replace regex pattern with the result of matching is the key trick here
    //or return $matches[0]; if you dont want to get captured parenthesized subpatterns
    //or you could return an array of both. its up to you how to do it.
    }else{
    return '';
    }
}

#/ Apply array Regex via much faster function (instead of a loop)
$results = array_map('cb_reg', $reg_arr); //returns regex results
$results = array_diff($results, array('')); //remove empty values returned

基本上,这是我能想到的最快的方式。

  1. 你不能将100s的正则表达式组合成一个调用,因为构建它是非常复杂的正则表达式,并且有几次机会失败匹配。这是最好的方法之一。

  2. 在我看来,与使用这种回调数组的方法相比,将大量的正则表达式组合成1个正则表达式(如果可能实现的话)在使用preg_match时执行起来会更慢。请记住,这里的关键是Callback function on array member values,这是处理PHP中类似情况的数组的最快方法

  3. 另请注意, callback on Array不等于looping the Array。循环较慢并且算法分析中具有“n”。但是数组元素的回调是内部的,并且相比之下非常快。

答案 2 :(得分:0)

您可以将所有正则表达式与“|”结合使用在他们之间。然后应用:http://www.rexegg.com/regex-optimizations.html,它将优化它,折叠常用表达式等。