棘手的问题:如何从多个正则表达式中排序结果

时间:2009-03-04 14:28:40

标签: php regex

我目前在一个preg_match中使用3个不同的正则表达式,使用或符号|分开他们。这非常有效。然而,第一和第二正则表达式具有相同类型的输出。例如[0]源文本[1]数量[2]名称 - 但是最后一个因为它使用不同的源文本排列结果:[0]源文本[1]名称[2]数量金额。

    preg_match('/^Guo (\d+) Cars @(\w+)|^AV (\d+) Cars @(\w+)|^@(\w+) (\d+) [#]?av/i', $source, $output);

由于Name可以是数字,因此无法进行简单检查以查看它是否为数字。有没有办法可以在正则表达式中切换顺序或者识别它匹配的正则表达式。速度至关重要,因此我不想使用3个单独的preg_match语句(以及更多内容)。

3 个答案:

答案 0 :(得分:3)

您可以使用命名捕获组:

preg_match('/^Guo (?P<number_amount>\d+) Cars @(?P<name>\w+)|^AV (?P<number_amount>\d+) Cars @(?P<name>\w+)|^@(?P<name>\w+) (?P<number_amount>\d+) [#]?av/i', $source, $output);

答案 1 :(得分:3)

三个单独的正则表达式不一定要慢。一个重要的声明将意味着正则表达式引擎的大量回溯。正则表达式优化的关键是尽快使引擎失败。你做了一些基准测试拉动它们吗?

在您的情况下,您可以使用PCRE的命名抓取(?<name>match something here),并替换为${name}而不是\1。我不是100%肯定这适用于preg_replace。我知道preg_match正确存储了某些特定的捕获。

PCRE需要使用PCRE_DUPNAMES选项进行编译,以便在您的案例中有用(如在RoBorg的帖子中)。我不确定PHP编译的PCRE DLL文件是否设置了该选项。

答案 2 :(得分:0)

我不知道PCRE支持duplicate subpattern numbers syntax (?| … )的版本。但试试这个正则表达式:

/^(?|Guo (\d+) Cars @(\w+)|AV (\d+) Cars @(\w+)|@(\w+) (\d+) #?av)/i

所以:

$source = '@abc 123 av';
preg_match('/^(?|Guo (\\d+) Cars @(\\w+)|AV (\\d+) Cars @(\\w+)|@(\\w+) (\\d+) #?av)/i', $source, $output);
var_dump($output);