在某个单词之前不包含特定单词的正则表达式

4

我正在寻找适用于以下结果的正则表达式:

字符串 = This is Cold Water and this is Hot Water, have some Water.

我想要检查这个字符串中是否有单词“Water”,并且该单词之前没有出现“Cold”和“Hot”这两个单词。

String mydata = "This is Cold Water and this is Hot Water, have some Water";
Pattern pattern = Pattern.compile("[^(Cold|Hot)]\sWater");
    Matcher matcher = pattern.matcher(mydata);
    if (matcher.matches()) {
        String s = matcher.group(1);
        System.out.println(s);
    }

但是它导致了无匹配结果。
1个回答

5

[^(Cold|Hot)]\sWater模式匹配除了(Co)之外的任何字符,然后是一个空格,然后是Water子字符串。 [^...]是一个否定字符类,您不能用它否定字符序列。

您可以使用带有负回顾后发断言的正则表达式。对于您的情况,最基本的形式是(?<!Cold\s|Hot\s),您还可以进一步自定义它。

例如,\s 只匹配一个空格,如果在 ColdWater 或者 HotWater 之间有两个或更多的空格,则回顾后查找将无法工作。在 Java 正则表达式中,您可以使用 限定量词(请参见约束宽度回顾后查找),因此您可以使用 \s{1,10} 允许回顾后查找“看到”后面的 1 到 10 个空格。
另一个增强功能是整个单词匹配,可以用 \b 包围单词,单词边界结构
请注意 Matcher#matches() 要求完全匹配,您实际上需要使用 Matcher#find()
这里是一个示例解决方案:
String mydata = "This is Cold Water and this is Hot Water, have some Water";
        Pattern pattern = Pattern.compile("\\b(?<!(?:\\bCold\\b|\\bHot\\b)\\s{1,10})Water\\b");
        Matcher matcher = pattern.matcher(mydata);
        if (matcher.find()) {
            System.out.println(matcher.group(0));
        }

查看Java在线演示

模式详细信息

  • \\b - 单词边界
  • (?<! - 负向零宽断言的开始,如果当前位置左侧紧挨着以下内容之一,则匹配失败:
    • (?: - 开始一个非捕获组,匹配以下两个选择之一:
      • \\bCold\\b - 整个单词 Cold
      • | - 或者
      • \\bHot\\b - 整个单词 Hot
    • ) - 非捕获组结束
    • \\s{1,10} - 1 到 10 个空格(如果您确定单词之间只有 1 个空格,则可以使用 \s
  • ) - 零宽断言结束
  • Water - 搜索词
  • \\b - 单词边界

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