有可能用正则表达式匹配嵌套对吗



我试图用regex解析一些BBCode,但嵌套结构让我头疼

我试图解析以下内容:

[COLOR="Red"]Red [COLOR="Green"]Green[/COLOR][/COLOR]

我已经想出了以下模式,我需要处理颜色属性周围的引号,但它只匹配第一个前导color和第一个结束color。在正确的嵌套排列中不匹配

[COLOR=("?)(.*?)("?)]([sS]*?)[/COLOR]

它是在dart中完成的,如下所示,但实际上我认为问题可能是我的regex模式,而不是dart实现

text = text.replaceAllMapped(RegExp(r'[COLOR=("?)(.*?)("?)]([sS]*?)[/COLOR]', caseSensitive: false, multiLine: true), (match) {
return '<font style="color: ${match.group(2)}">${match.group(4)}</font>';
});

匹配的大括号(任何类型(都不是正则的。众所周知,这是一个无上下文的问题(可以由堆栈机器解决,也可以由无上下文语法指定(,但不是正则的(可以由有限状态机解决,也可由正则表达式指定(。而通常实现的";正则表达式";可以做一些非常规的事情(由于反向引用(,这不是其中之一。

通常,我建议使用RegExp来标记输入,然后自己在上面构建基于堆栈的机器。

在这里,因为它足够简单,我只需要匹配开始和结束标记,并分别替换它们,而不尝试在它们之间匹配文本。

var re = RegExp(r'[COLOR="(w+)"]|[/COLOR]');
text = text.replaceAllMapped(re, (m) {
var color = m[1]; // The color of a start tag, null if not start tag.
return color == null ? "</span>" : ​"<span style='color:$color'>";
});

如果你想检查标签是否平衡,我们回到堆栈(在这种情况下很简单,它只是一个计数器(:

var re = RegExp(r'[COLOR="(w+)"]|[/COLOR]');
var nesting = 0;
text = text.replaceAllMapped(re, (m) {
var color = m[1];
if (color == null) {
if (nesting == 0) {
throw ArgumentError.value(text, "text", "Bad nesting");
}
nesting--; // Decrement on close tag.
return "</span>";
}
nesting++; // Increment on open-tag.
return ​"<span style='color:$color'>";
});
if (nesting != 0) {
throw ArgumentError.value(text, "text", "Bad nesting");
}

最新更新