Java正则表达式匹配不被#{.*和.*}包围的内容

3
我正在尝试替换字符串中所有出现的true,例如在"true && 0 || 1"中。
这些字符串可能包含变量值,标记为#{varname}。我不想替换被#{}包围的实例。
例如:
"true && #{ab_true_cd} || 0"
应转换为
"1 && #{ab_true_cd} || 0" 我尝试使用以下正则表达式:
(?<!\#\{[^\}]*)true 使用上述正则表达式时,我得到了以下错误:
回溯引用组没有明显的最大长度,位于索引13附近。
你知道解决方案或更好的方法吗?还是有比使用正则表达式更好的方法吗?
我使用http://regexe.com测试表达式。

你是否觉得更合理的做法是将你不想替换的实例定义为“true 不是单独的单词”?我的意思是,替换所有独立的 true,但不替换它在单词中间/开头/结尾的情况。 - RealSkeptic
1
你正在寻找这个 - Lucas Trzesniewski
回顾总是应该有定义的最大长度。您不能使用 *,因为它具有无限潜在长度。您可以通过使用 {,80}(或其他比您潜在字符串长度大100%的数字)来解决问题,但这并不好。在您的情况下,您可以使用 \btrue\b\b 是单词的开头或结尾)。 - TEXHIK
感谢大家的回答。我的问题得到了Lucas Trzesniewski和stribizhev提出的最佳解决方案。 - 2manyvcos
2个回答

2
以下是两种使用正则表达式的解决方案(都在评论中提到了,分别由Lucas TrzesniewskiTEXHIK提出):
  • 一种受限宽度的向后查找解决方案(Java正则表达式引擎支持具有限制量词的向后查找):

Java代码:

String rx = "(?<!#\\{[^{}]{0,500})\\btrue\\b";
String str = "true && #{ab_true_cd} || 0";
System.out.println(str.replaceAll(rx, "1"));

请查看演示(输出:1 && #{ab_true_cd} || 0

正则表达式(?<!#\\{[^{}]{0,500})\\btrue\\b匹配任何以单词true结尾的内容,该内容不以#{开头,后跟0到500个字符,这些字符不是{}

  • 另一种解决方案基于匹配要替换的内容和匹配要保留的内容并进行捕获的方法。

代码:

String s = "true && #{ab_true_cd} || 0";
StringBuffer result = new StringBuffer();
Matcher m = Pattern.compile("(#\\{[^{}]*})|\\btrue\\b").matcher(s);
while (m.find()) {
    if (m.group(1) != null) {
        m.appendReplacement(result, m.group(1)); // if a #{} block found, restore it
    }
    else {
        m.appendReplacement(result, "1"); // else, replace true with 1
    }
}
m.appendTail(result);
System.out.println(result.toString());

查看另一个IDEONE演示


1
谢谢!运行得很好。 - Mordechai
https://github.com/update4j/update4j/blob/7c85415aa9c0eaddc007a5febb09089f89d63c2f/src/main/java/org/update4j/util/PropertyManager.java#L244 - Mordechai
@Mordechai 在Java 9中,有另一种不错的方法可以使用replaceAll来实现,但需要使用Pattern.compileMatcher实例。 - Wiktor Stribiżew

0
你可以按'&&'或'||'拆分,将每个部分与单词“true”进行比较,用“1”替换,然后再合并它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接