【问题标题】:Java RegEx match if not surrounded by #{.* and .*}如果没有被 #{.* 和 .*} 包围,Java RegEx 匹配
【发布时间】:2015-12-25 13:34:46
【问题描述】:

我正在尝试替换字符串中单词 true 的所有实例, 比如"<b>true</b> &amp;&amp; 0 || 1"

这些字符串可能包含变量值,标记为#{varname}。 我不想替换被#{} 包围的实例。

示例:
"<b>true</b> &amp;&amp; #{ab_true_cd} || 0"
应转换为
"<b>1</b> &amp;&amp; #{ab_true_cd} || 0"

我尝试使用这个正则表达式:
(?&lt;!\#\{[^\}]*)true

通过使用上面的 RegEx,我得到了以下错误:
后视组在索引 13 附近没有明显的最大长度

您知道解决方案或更好的方法吗?或者有没有比使用 RegEx 更好的方法?

我使用http://regexe.com 来测试表达式。

【问题讨论】:

  • 将不想替换的实例定义为“true 本身不是一个词”不是更有意义吗?我的意思是,当它独立时替换所有true,而不是当它位于单词的中间/开头/结尾时。
  • 您正在寻找this
  • Look-behind 总是应该定义最大长度。你不能使用*,因为它的潜在长度是无限的。您可以使用{,80}(或其他比您的潜在字符串大 100% 的数字)四处走动,但这并不好。在您的情况下,您可以使用\btrue\b\b 是世界的开始或结束)
  • 谢谢大家的回答。 Lucas Trzesniewski 和 stribizhev 提到了我的问题的最佳解决方案。

标签: java regex


【解决方案1】:

这里有 2 个使用正则表达式的解决方案(Lucas TrzesniewskiTEXHIK 在 cmets 中都提到过):

  • 宽度受限的后视解决方案(Java 正则表达式引擎支持内部具有限制量词的后视):

Java 代码:

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

demo(输出:1 &amp;&amp; #{ab_true_cd} || 0

正则表达式 (?&lt;!#\\{[^{}]{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());

another IDEONE demo

【讨论】:

  • 谢谢!像魅力一样工作。
  • @Mordechai 在 Java 9 中,还有另一种不错的方法可以使用 replaceAll,但需要使用 Pattern.compileMatcher 实例。
【解决方案2】:

你可以用'&&'或'||'分割,将每个部分与单词'true'比较,替换为'1',然后再次合并

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多