我正在研究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
答案 0 :(得分:4)
原子组之后的+
量词表示正则表达式引擎将尝试将组内的模式匹配一次或多次。这与第二个表达式不同,在第二个表达式中,引擎只会尝试匹配模式一次。
+
后面没有延迟修饰符?
,所以它会贪婪地匹配,即尽可能多次匹配。
分组可能是原子的,因为除了使组不捕获之外,它还可以防止在整个子表达式的每次完全匹配之后的任何回溯。
如果群组末尾的\n*
无法与换行符匹配,则由于+
引擎将从头开始尝试再次匹配群组。如果它没有这样做,那么因为该组是原子的,所以将返回现有的匹配。
如果该组不是原子的,那么在尝试再次匹配组的开始之前,引擎将回溯以尝试以不同的方式匹配刚刚成功匹配的内容。
例如,如果匹配的最后三个字符是换行符\n*
,它将首先提供最后一个字符并尝试再次匹配组的开头。如果失败了,它会给另一个换行符再试一次,依此类推。
由于(.+\n)*
匹配的内容以及.
和{匹配了多少字符的灵活性,回溯将继续到+
序列。 {1}},在尝试再次进行匹配之前,引擎可以通过多种方式匹配模式。
字符串的相同部分可以通过许多不同方式与整个子表达式匹配,因此在引擎确定不可能进一步匹配之前可能存在大量低效,耗时的回溯。
原子组表示意味着可以避免这种情况。