Java:哪个解析器最适合根据括号对匹配文本?

时间:2016-07-28 10:30:40

标签: java regex parsing

字符串示例:

"(这是1级。(这是2级)。这是3级。回到2级。)回到1级。)"

如果事先不知道会有多少级别的括号(即级别3中可能有4级,5级,6级等),我的理解是正则表达式不可能匹配上例中的2级文本。因此,对于此示例,使用正则表达式无法匹配以下内容:

"(这是2级。(这是3级)。回到2级。)"

我已经阅读过使用解析器来做到这一点,但我不确定哪个是最好的。我会寻求易用性,速度和与Java的兼容性。任何有关这方面的帮助将不胜感激。

2 个答案:

答案 0 :(得分:4)

我去年做过这样的事情。

很简单,您可以从搜索最后一个(开始,然后存储就是索引。然后在存储索引后搜索第一个)。您只需要一个子字符串来提取这两个索引之间的文本并完成:)

对于下一个级别,使用上一个索引查找上一个/下一个( / )并且您可以轻松解析;)

以下是打印每个级别的简单代码示例:

public static void main(String... args) {
        String s = "(This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.)";
        searchInto(s);
    }

    public static void searchInto(String s){
        searchInto(s, s.length(), 0);
    }

    public static void searchInto(String s, int from, int to){
        int nextOpen = s.lastIndexOf("(", from-1);
        if(nextOpen >= 0){
            int nextClose = s.indexOf(")", to);

            System.out.println(s.substring(nextOpen + 1, nextClose));
            searchInto(s, nextOpen, nextClose + 1);
        } else
            return;
    }

将打印:

This is level 3.
This is level 2. (This is level 3.) Back to level 2.
This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.

编辑:

这应该涵盖更多的基础。这将搜索彼此靠近的内部块AND块。

public static void main(String... args) {
        searchInto("(This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.)");
        searchInto("(L1) (L2) (L3)");
        searchInto("(L1) (L2 (L2a)) (L3)");
    }

    public static void searchInto(String s){
        searchInto(s, s, s.length(), 0);
    }

    public static void searchInto(String s, String original, int from, int to){
        int nextOpen = s.lastIndexOf("(", from);
        if(nextOpen >= 0){
            int nextClose = s.indexOf(")", nextOpen);
            String tmp = original.substring(nextOpen + 1, nextClose);
            System.out.println(tmp); //Print the result, use a List to store or treat it directly.
            s = s.substring(0, nextOpen) + "#" + s.substring(nextOpen + 1, nextClose) + "#" + s.substring(nextClose + 1);
            searchInto(s, original, nextOpen - 1, nextClose + 1);
        } else
            return;
    }

将输出:

This is level 3.
This is level 2. (This is level 3.) Back to level 2.
This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.

L3
L2
L1

L3
L2a
L2 (L2a)
L1

通过使用替代String替换已找到的字符,我阻止代码卡在索引上。但我打印原始值以打印正确的值(没有#字符用于替换已发现的( )

这有点贵,所以如果你需要覆盖每一个结构,那就真的很好。

答案 1 :(得分:1)

这应该适用于这样的字符串“(Lvl1(Lvl2)Lvl1(lvl2bis)Lvl1)”:

private static void printLevels(String in) {
    List<String> levels = new ArrayList<>();
    List<Integer> indexes = new ArrayList<>(); 
    for (int i = 0; i < in.length(); i++) {
        if (in.charAt(i) == '(') {
            indexes.add(i);
        } else if (in.charAt(i) == ')') {
            levels.add(in.substring(indexes.remove(indexes.size()-1), i+1));
        }
    }
    for (String string : levels) {
        System.out.println(string);
    }
}

此:

String in =  "(Lvl1 (Lvl2) Lvl1 (lvl2bis) Lvl1)";
printLevels(in);

将打印:

(Lvl2)
(lvl2bis)
(Lvl1 (Lvl2) Lvl1 (lvl2bis) Lvl1)