4

我正在使用正则表达式<@(.+?)@>来匹配模式,例如:

<@set:template default.spt @>

它工作正常,但我遇到了需要嵌套模式的情况,例如:

<@set:template <@get:oldtemplate @> @>

我没有得到父对(<@和@>),而是得到以下内容:

<@set:template <@get:oldtemplate @>

我不希望它得到孩子,我只想要所有嵌套情况下最外层的父母。如何修复我的正则表达式以便它为我做这件事?我想如果我知道如何要求父母内部<@有一个,我可以做到这一点@>,但我不知道如何强制执行。

4

2 回答 2

5

你所描述的是一种“非常规语言”。它不能用正则表达式解析。

好的,如果您愿意限制嵌套级别,从技术上讲,您可以使用正则表达式来做到这一点。但是会很丑。

如果您可以将不包含 @ 的条件放在标签中,以下是如何使用几个(增加)最大嵌套深度来解析您的东西:

no nesting: <@[^@]+@>
up to 1:    <@[^@]+(<@[^@]+@>)?[^@]*@>
up to 2:    <@[^@]+(<@[^@]+(<@[^@]+@>)?[^@]*@>)?[^@]*@>
up to 3:    <@[^@]+(<@[^@]+(<@[^@]+(<@[^@]+@>)?[^@]*@>)?[^@]*@>)?[^@]*@>
...

如果你不能在你的标签中禁止单独的@,你将不得不用这样的[^@]东西替换每个实例:(?:[^<@]|<[^@]|@[^>])

想一想,然后考虑扩展您的正则表达式以解析多达 10 个深度嵌套。

在这里,我会为你做的:

<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[
^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<
[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@[^>])+(<@(?:[^<@]|<[^@]|@
[^>])+(<@(?:[^<@]|<[^@]|@[^>])+@>)?(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>]
)*@>)?(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>])*@
>)?(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>])*@>)?
(?:[^<@]|<[^@]|@[^>])*@>)?(?:[^<@]|<[^@]|@[^>])*@>

我希望我的回答表明正则表达式不是解析语言的正确工具。传统的词法分析器(标记器)和解析器组合会做得更好,速度更快,并且可以处理无限嵌套。

于 2013-05-16T20:17:05.273 回答
1

我不认为你可以用正则表达式来做到这一点,请参阅这个问题的答案,它提出了类似的问题。正则表达式不足以处理任意级别的嵌套,如果您只有 2 级嵌套,那么它应该是可能的,但也许正则表达式不是这项工作的最佳工具。

于 2013-05-16T20:01:22.523 回答