我目前正在创建bbcode解析引擎,我遇到了一些我自己无法弄清楚的情况。
问题是,我遇到了一个与此问题完全相同的问题: Apache / PHP on Windows crashes with regular expression
这意味着,如果我做了类似下面的示例,那么由于递归计数达到690(PCRE的内存限制为1MB),Apache崩溃了:
$txt = '[b]'.str_repeat('a', 338).'[/b]'; // if I change repeat count to lower value it's ok
$regex = '#\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))](?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)\[/(?P=tag)]#mi';
echo preg_replace_callback($regex, function($matches) { return $matches['content']; }, $txt);
所以我需要以某种方式最大限度地减少我的正则表达式*
和+
的需要,但这就是我没有想法的地方所以我可能会提出建议。
欢迎解析bbcode(可以处理嵌套标签)的其他方法。 但是,我不想使用已经构建的类或其他东西。我喜欢独自做事!
我也研究了PECL和Pear HTML_BBCodeParser。但我不希望我的应用程序依赖于扩展。我更有可能做一些检查该扩展的脚本,如果它不存在,请使用我在这里尝试做的BBCode解析器。
对不起,如果我的描述很暗淡,我不是英语专业人士^^
EDIT。所以正则表达式解释说:
\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))]
这是我的开场标签。我使用过命名组。使用'tag'我识别标签,并使用'attributes'识别标签属性。将标签视为属性。那么这里发生了什么?我尝试匹配标记,当标记匹配时,我会尝试匹配=
符号之后的任何内容或\s
之后的任何内容(spacer),直到它到达标记结束]
。
(?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)
现在我在这里尝试匹配内容。这是棘手的部分。我正在寻找任何没有的字符[如果我发现任何字符,那么我检查它是不是我的结束标记或递归,我告诉正则表达式引擎这样做直到....
\[/(?P=tag)]
...找到了结束标记。
答案 0 :(得分:3)
你的正则表达式,特别是零宽度断言(环视)导致正则表达式引擎灾难性地回溯。故事的道德:不应该使用正则表达式不能来解析非常规的语言。如果你有嵌套结构,那不是常规语言。
事实上,我认为BBCode是邪恶。 BBCode是一种标记语言,由懒惰的程序员发明,他们不想以正确的方式过滤HTML。结果,我们现在有一个很难实现的松散“标准”。以正确的方式过滤HTML:
答案 1 :(得分:2)
我打算建议一个BBCodeParser ......
我也研究了PECL和Pear HTML_BBCodeParser。但我不希望我的应用程序依赖于扩展
我发现这很奇怪。为什么重新发明轮子?良好的软件工程原则之一是DRY(不要重复自己)。您正在尝试解决已经解决的问题。
我喜欢独自做事!
这本身并不坏,但有时候你最好使用经过验证的真正解决方案;一个比你自己更好的测试和更强大的(你发现)。这样你就可以花时间解决你真正想要解决的问题而不是解决已经解决的问题。不要陷入重新发明轮子的陷阱。 :)
我的建议(和解决方案)是使用BBCode解析器。
修改强>
另一件事是你正在解析像HTML一样的东西。这种性质的东西不容易被正则表达式解析。