我怎么写这个正则表达式? ungreedy相关

时间:2012-11-22 22:01:42

标签: php regex pcre

我很抱歉这个糟糕的头衔,但这是一个非常通用的问题

我必须匹配这种模式

;AAAAAAA(BBBBBB,CCCCC,DDDDDD)
  • AAAAA =从“;”开始的所有字符to“(”(both;(not included)
  • BBBBB =从“(”到“,”开头的所有字符(两者(不包括在内)
  • CCCCC =所有字符从“,”到“,”(两者都包括在内)
  • DDDDD =从“,”到“)”(两者)开头的所有字符都不包括在内)

“x和y之间的所有字符”是每次都会导致我的问题

:(

我正在使用PHP,我必须匹配所有出现的这种模式(preg_match_all),遗憾的是,它可以在多行上

提前谢谢!

2 个答案:

答案 0 :(得分:3)

我建议你不要使用不合理的量词,而是将所有重复与其分隔符互斥。这是什么意思?例如,这意味着A可以是除(之外的任何字符。给这个正则表达式:

;([^(]*)[(]([^,]*),([^,]*),([^)]*)[)]

甚至不需要最后[)]

PHP代码将如下所示:

preg_match_all('/;([^(]*)[(]([^,]*),([^,]*),([^)]*)[)]/', $input, $matches);
$fullMatches = $matches[0];
$arrayOfAs = $matches[1];
$arrayOfBs = $matches[2];
$arrayOfCs = $matches[3];
$arrayOfDs = $matches[4];

正如评论所示,我的逃避技术是一个品味问题。这个正则表达式当然等于:

;([^(]*)\(([^,]*),([^,]*),([^)]*)\)

但我认为这看起来比其他变种更不匹配/不平衡。带你去挑选!

最后,对于为什么这种方法比使用ungreedy(懒惰)量词更好的问题。 Here is some good, general reading.基本上,当你使用不合理的量词时,引擎仍然需要回溯。它首先尝试重复一次,然后注意到(之后不匹配。所以它必须回到重复并消耗另一个角色。但是(仍然不匹配,所以再次回到重复。然而,通过这种方法,当第一次进行重复时,引擎将尽可能多地消耗。当消耗掉所有非(个字符时,引擎就能立即匹配以下(

答案 1 :(得分:1)

你可以使用类似这样的代码:

preg_match_all('/;(.*?)\((.*?),(.*?),(.*?)\)/s',$text,$matches);

ideone.com上查看。

基本上,你可以使用.*?(问号是不合适的),确保转义括号,你可能需要s修饰符让它在多行上运行。

变量将在数组中:$matches