我试图用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");
}