如何在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
)
)