【问题标题】:Java parse nested "tags"Java解析嵌套的“标签”
【发布时间】:2015-07-16 07:12:04
【问题描述】:

我有“标签”的格式

{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 表示
  • 标签可以任意嵌套,但只能在第一个位置
  • 空格 IS 重要(它是字段的一部分,不应忽略)
  • 可以有任意数量的标志字段
  • 所有字段都可以包含任何字符(包括idcontext),所以{、} 和|必须可以用 \ 转义(例如 \| 不会分隔字段)

我知道我可以通过遍历字符串并跟踪我何时点击标签开始、我的嵌套深度、我的深度何时达到 0 以及抓取其间的所有内容来解析它,但这有点痛苦。

如果可能的话,我想使用正则表达式,但 Java 不支持递归正则表达式。

解析这个的最好方法是什么?

额外信息

如果有区别,“标签”将被解析为一个对象(解析和构建的对象),然后可以将对象呈现为它所代表的字符串。这就是为什么正则表达式更可取的原因,因为我可以使用Matcher::appendReplacementMatcher::appendTail

【问题讨论】:

  • Java 正则表达式无法平衡任意嵌套的括号。只需编写代码,坚持常规方法即可。
  • 我害怕那个。
  • 我刚刚写了一个关于 Java 正则表达式不支持嵌套平衡元素 here 的答案。它引用了this other question 关于java 解析器。希望对您有所帮助...
  • 我最终构建了自己的解析器。这比我预期的要容易得多。
  • 如果您愿意,您可以发布一个答案,其中包含将语法解析为您自己的问题的代码并接受它。

标签: java regex parsing


【解决方案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() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-09
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多