$string = '## aaa bbb';
$pattern = '/^(\n)?\s{0,}#{1,6}\s+| {0,}(\n)?\s{0,}#{0,} {0,}(\n)?\s{0,}$/';
$replacement = '$1$2$3';
echo preg_replace($pattern, $replacement, $string);
If the space between "aaa" and "bbb" is around 50 (or less), I DO get the correct result. BUT if I increase the number, say there are 100 space between "aaa" and "bbb". I get null. How can I find out the reason?
答案 0 :(得分:1)
该模式匹配两个替代方案,一个^(\n)?\s*#{1,6}\s+
和另一个 *(\n)?\s*#* *(\n)?\s*$
。
第一个可以,尽管建议将\n
设为可选,而不是将整个组设为可选。
第二个模式 *(\n)?\s*#* *(\n)?\s*$
是非常低效的模式,因为有\s*
个模式跟随可选的\n
模式,而该模式又以 *
开头图案。当没有\n
时,\s*
可能会“落入” *
,并且leads to catastrophical backtracking会与部分模式匹配但最终子模式失败。
因此,您可以使用
/^(\n?)\s*#{1,6}\s+| *(?:(\n)\s*)?#* *(?:(\n)\s*)?$/
请参见regex demo
此处的关键点是(?:(\n)\s*)?
个部分,其中\n
是必需的,只有在所有常规空格都与 *
然后匹配{{ 1}}仅在之前有\s*
时才会尝试,这样可以确保没有子模式落入另一个模式中。