Markdown正则表达式中的原子组

时间:2013-02-02 14:15:59

标签: php regex markdown

我正在研究dflydev的 MarkdownParser 。 在 doBlockQuotes line 1167中,他们在整个表达式上使用 Atmoic Group 。 我知道 Atmoic Grouping 但我不明白它在这方面有何帮助?

为什么:

/
(                     # Wrap whole match in $1
    (?>
        ^[ ]*>[ ]?    # ">" at the start of a line
        .+\n          # rest of the first line
        (.+\n)*       # subsequent consecutive lines
        \n*           # blanks
    )+
)
/xm

比这更好:

/
(                     # Wrap whole match in $1
        ^[ ]*>[ ]?    # ">" at the start of a line
        .+\n          # rest of the first line
        (.+\n)*       # subsequent consecutive lines
        \n*           # blanks
)
/xm

1 个答案:

答案 0 :(得分:4)

原子组之后的+量词表示正则表达式引擎将尝试将组内的模式匹配一​​次或多次。这与第二个表达式不同,在第二个表达式中,引擎只会尝试匹配模式一次。

+后面没有延迟修饰符?,所以它会贪婪地匹配,即尽可能多次匹配。

分组可能是原子的,因为除了使组不捕获之外,它还可以防止在整个子表达式的每次完全匹配之后的任何回溯。

如果群组末尾的\n*无法与换行符匹配,则由于+引擎将从头开始尝试再次匹配群组。如果它没有这样做,那么因为该组是原子的,所以将返回现有的匹配。

如果该组不是原子的,那么在尝试再次匹配组的开始之前,引擎将回溯以尝试以不同的方式匹配刚刚成功匹配的内容。

例如,如果匹配的最后三个字符是换行符\n*,它将首先提供最后一个字符并尝试再次匹配组的开头。如果失败了,它会给另一个换行符再试一次,依此类推。

由于(.+\n)*匹配的内容以及.和{匹配了多少字符的灵活性,回溯将继续到+序列。 {1}},在尝试再次进行匹配之前,引擎可以通过多种方式匹配模式。

字符串的相同部分可以通过许多不同方式与整个子表达式匹配,因此在引擎确定不可能进一步匹配之前可能存在大量低效,耗时的回溯。

原子组表示意味着可以避免这种情况。