如何在Java中替换方括号()、保留内容并标记结果?

如何在Java中替换方括号()、保留内容并标记结果?,java,regex,brackets,replaceall,Java,Regex,Brackets,Replaceall,我想替换字符串中的括号,同时标记和添加换行符,就像漂亮的打印一样 (foo) AND ((bar) OR (baz)) 变成 ( foo ) AND ( ( bar ) OR ( baz ) ) 我试过: "((foo) OR ((bar)(baz)))".replaceAll("\\(

我想替换字符串中的括号,同时标记和添加换行符,就像漂亮的打印一样

 (foo) AND ((bar) OR (baz))
变成

     (
          foo
     )
AND
     (
          (
               bar
          )
     OR
          (
          baz
          )
     )
我试过:

   "((foo) OR ((bar)(baz)))".replaceAll("\\((.*?)\\)", "\\(\n\t$1\n\\)")

但这并不完全有效。

劳恩·阿祖雷弗格是对的。您提供的表达式不是正则表达式,因此无法使用正则表达式引擎对表达式进行修饰。在我看来,最好的办法就是编写一个解析器来处理这个任务。我总是试图将解析器逻辑与处理业务的代码分开。您可以注意到,在
ExpressionListener
的实现中,处理座椅格式化的逻辑。下面您可以找到代码

public class PrettyPrintExample {

    private interface ExpressionListener {

        void lb();

        void rb();

        void content(String content);

    }

    private enum Type {
        LB, RB, STRING, END
    }

    private static class Token {
        Type type;
        String value;

        public Token(Type type, String value) {
            super();
            this.type = type;
            this.value = value;
        }

        @Override
        public String toString() {
            return "Token [type=" + type + ", value=" + value + "]";
        }
    }

    private static class Lexer {

        private int current;
        private String input;

        public Lexer(String input) {
            this.input = input;
        }

        private char getChar() {
            return input.charAt(current++);
        }

        private void unputChar() {
            current--;
        }

        private boolean hasNextChar() {
            return current < input.length();
        }

        Token next() {

            if (!hasNextChar()) {
                return new Token(Type.END, "");
            }

            char c = getChar();

            while (Character.isWhitespace(c)) {
                c = getChar();
            }

            if (c == '(') {
                return new Token(Type.LB, "(");
            }

            if (c == ')') {
                return new Token(Type.RB, ")");
            }

            unputChar();

            StringBuilder buffer = new StringBuilder();
            while (hasNextChar()) {

                c = getChar();

                if (c != '(' && c != ')' && !Character.isWhitespace(c)) {
                    buffer.append(c);
                } else {
                    unputChar();
                    break;
                }

            }

            return new Token(Type.STRING, buffer.toString());

        }
    }

    private static Lexer lexer;
    private static Token currentToken;

    public static void parse(String line, ExpressionListener listener) {
        lexer = new Lexer(line);
        currentToken = lexer.next();
        expression(listener);
        consume(Type.END);
    }

    private static void expression(ExpressionListener listener) {

        while (true) {

            if (match(Type.STRING)) {
                listener.content(currentToken.value);
                consume(Type.STRING);
            } else if (match(Type.LB)) {
                consume(Type.LB);
                listener.lb();
                expression(listener);
                consume(Type.RB);
                listener.rb();
            } else {
                break;
            }

        }

    }

    private static boolean match(Type type) {
        return type == currentToken.type;
    }

    private static void consume(Type type) {
        if (!match(type)) {
            throw new RuntimeException(String.format("Should be %s is %s", type.name(), currentToken.type.name()));
        }
        currentToken = lexer.next();
    }

    public static void main(String[] args) {
        String line = "(foo) AND ((bar) OR (baz))";
        parse(line, new ExpressionListener() {

            private int indent = 0;

            private void indent(int indent) {
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < indent; i++) {
                    builder.append("\t");
                }
                System.out.print(builder.toString());
            }

            private void nl() {
                System.out.println();
            }

            @Override
            public void lb() {
                indent(++indent);
                System.out.print("(");
                nl();
            }

            @Override
            public void rb() {
                indent(indent);
                System.out.print(")");
                indent--;
                nl();
            }

            @Override
            public void content(String content) {
                indent(indent);
                System.out.print(content);
                nl();
            }
        });

    }

}

我知道在您的案例中使用CFL解析器并不是一个最简单的解决方案,但请注意,如果您的表达式变得非常复杂,那么扩展解析器将非常容易。

括号中表达式的语法不是正则的,因此您不能使用正则表达式来解析并根据其语法修改它。您可能需要编写解析器,例如使用递归下降或类似方法的解析器。不要尝试使用正则表达式解析非正则内容,否则将发生在您身上。
    (
    foo
    )
AND
    (
        (
        bar
        )
    OR
        (
        baz
        )
    )