2

我目前正在创建 bbcode 解析引擎,但遇到了我自己无法解决的情况。

问题是,我遇到了一个与此完全相同的问题: Windows 上的 Apache / PHP crash with regular expression

这意味着,如果我做出类似下面示例的操作,Apache 会因为递归计数达到 690(PCRE 的内存限制为 1MB)而崩溃:

$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 解析器。

对不起,如果我的描述令人沮丧,我不是英语专业人士^^

编辑。所以正则表达式解释说:

\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))]

这是我的开始标签。我使用了命名组。使用“标签”标识标签,使用“属性”标识标签属性。也可以将标签视为一个属性。那么这里发生了什么?我尝试匹配一个标签,当一个标签匹配时,我尝试匹配=符号之后的任何内容或\s(spacer) 之后的任何内容,直到它到达 tag closure ]

(?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)

现在我在这里尝试匹配内容。这是棘手的部分。我正在寻找任何不是 [ 的字符,如果找到任何字符,则检查它是否不是我的结束标签或递归,并告诉正则表达式引擎这样做,直到...。

\[/(?P=tag)]

...找到结束标签。

4

2 回答 2

3

您的正则表达式,尤其是零宽度断言(环视)导致正则表达式引擎灾难性地回溯。故事的寓意:应该使用正则表达式来解析不规则的语言。如果您有嵌套结构,那不是常规语言。

事实上,我认为 BBCode 是邪恶的。BBCode 是一种标记语言,由不想以正确方式过滤 HTML 的懒惰程序员发明。结果,我们现在有了一个难以实施的松散“标准”。以正确的方式过滤您的 HTML:

http://htmlpurifier.org/

于 2010-08-31T21:35:05.643 回答
2

我打算建议一个BBCodeParser ...

我还研究了 PECL 和 Pear HTML_BBCodeParser。但我不希望我的应用程序依赖于扩展

我觉得这很奇怪。为什么要重新发明轮子?好的软件工程的原则之一是 DRY(不要重复自己)。你正在尝试解决一个已经解决的问题。

我喜欢自己做事!

这本身并不坏,但有时您最好使用经过验证的真实解决方案;一个比您自己的测试更好且更强大的(正如您所发现的那样)。这样,您将花时间在您真正想要解决的问题上,而不是解决已经解决的问题。不要陷入重新发明轮子的陷阱。:)

我对您的建议(和解决方案)是使用 BBCode 解析器。

编辑

另一件事是您正在解析类似 HTML 的内容。这种性质的事物不容易被正则表达式解析。

于 2010-08-31T21:34:11.247 回答