问题描述
我有格式的“标签”
{id|attribute|context|comment|flag1|flag2|...}
问题是, id
部分可以是嵌套标签,如下所示:
{{id|attribute|||flag}|attribute}
甚至
{{{{id|attribute}|attribute}|attribute}|attribute}
嵌套理论上可以无限期地继续下去。 我正在尝试寻找一种很好的方法来解析可能包含任意数量的这些字符串的文本,如下所示
{7953|title} is a {7953|generic} in {{7953|setting}|title}.
{5514|name} lives in {7953|title}.
{{{3216|carrier|20140205191631}|origin}|pronoun||deeply rooted|first|possessive} favorite ...
你明白了。 我需要一种从给定的文本块中找到每个“标签”的方法。 注意事项
- 场限定符为|
-
标签仅需要前两个字段
- 缺少的字段由连续的| s表示
- 标签可以任意嵌套,但只能在第一个位置
- 白色空间显著(它是场的一部分,不应该被忽略)
- 可以有任意数量的标志字段
-
所有字段的内部都可以包含任何字符(包括
id
和context
),因此{,}和| 必须使用\\可以转义(例如\\ |不会分隔字段)
我知道我可以通过遍历字符串并跟踪何时击中标签开始,嵌套的深度,深度为0并抓住所有内容来解析它,但这有点麻烦。
我想尽可能使用正则表达式来做,但是Java不支持递归正则表达式。
解析此内容的最佳方法是什么?
额外信息
如果有所不同,则将“标签”解析为一个对象(解析和构建的对象),然后可以将该对象呈现为其表示的字符串。
这就是为什么使用regex更好,因为我可以使用Matcher::appendReplacement
和Matcher::appendTail
。
1楼
这是我用来解析包含“标签”的文本的代码:
public static String parseText(String text) {
StringBuilder oldText = new StringBuilder(text);
StringBuilder newText = new StringBuilder();
int firstTag = oldText.indexOf("{");
FullBreak:
while (firstTag >= 0) {
newText.append(oldText.substring(0, firstTag));
oldText.delete(0, firstTag);
int depth = 1;
int position = 0;
while (depth > 0) {
position++;
if (position > oldText.length() - 1) {
break FullBreak;
}
if (oldText.charAt(position) == '{' && oldText.charAt(position - 1) != '\\') {
depth++;
}
if (oldText.charAt(position) == '}' && oldText.charAt(position - 1) != '\\') {
depth--;
}
}
position++;
newText.append(parseTag(oldText.substring(0, position)).render());
oldText.delete(0, position);
firstTag = oldText.indexOf("{");
}
newText.append(oldText);
return newText.toString();
}
在这种情况下, parstTag(String)
返回一个Tag
,它具有render()
方法。