java - 对字符串执行替换但忽略某些模式

标签 java regex

我(正则表达式菜鸟)正在尝试对包含某种模式的字符串执行替换操作。例如

AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA

在上面我试图替换所有 AI忽略 A s 在大括号内。

为此,我可以做的是拆分模式上的整个字符串并执行替换,然后连接字符串。

我想知道正则表达式中是否有更短的方法,以便我可以执行类似的操作

String str = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
str = str.replaceButIgnorePattern("A", "I","\\{(.*?)\\}");
System.out.print(str);   //III-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-III

图案可以是这样的

  1. 包含任意字符

  2. 可以位于字符串的开头、中间或末尾

最佳答案

考虑到没有嵌套大括号,解决方案是匹配最接近的 {} 内的子字符串> 并匹配并捕获要替换的模式,然后检查组 1 是否不为空,然后采取相应行动。

在 Java 9+ 中,您可以使用

String text = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
Pattern r = Pattern.compile("\\{[^{}]*}|(A)");
Macher m = r.matcher(text);
String result = m.replaceAll(x -> x.group(1) != null ? "I" : x.group() );
System.out.println( result );

请参阅online demo .

此处,\{[^{}]*} 匹配 {、除 {} 之外的任何 0+ 个字符,然后 } 或 (|) 将 A 捕获到组 1。

旧 Java 版本的等效代码:

String text = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
Pattern r = Pattern.compile("\\{[^{}]*}|(A)");
Matcher m = r.matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
    if (m.group(1) == null) {
        m.appendReplacement(sb,  m.group(0));
    } else {
        m.appendReplacement(sb,  "I");
    }
}
m.appendTail(sb);
System.out.println(sb);

请参阅online Java demo .

您还可以对任何 Java 版本使用通用解决方法:

str = str.replaceAll("A(?![^{}]*})", "I");

其中 (?![^{}]*}) 确保后面没有出现 0+ 次 {}紧邻当前位置右侧的 }注意这种方法意味着字符串包含均衡数量的左大括号/右大括号。

关于java - 对字符串执行替换但忽略某些模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59301911/

相关文章:

javascript - AngularJS - 突出显示部分文本会导致非英语语言中的单词损坏

java - 短语的正则表达式包含文字和数字,但并非所有短语都是仅具有固定范围长度的数字

regex - Bash 脚本 find/sed 不起作用

java - jetty 9.0.3 中的 Close_wait 过多

math - 为什么在 util Random 类中使用 48 位种子?

java - 没有基类访问的 hibernate 字段继承

java - 使用 poi 从 Excel 中检索值

regex - 如何在 Go 中执行不区分大小写的正则表达式?

javascript - 如何查找具有部分固定模式的子字符串

java - 如何将 java 循环与 SQL 条件选择混合