【问题标题】:Regex match only if text contains something before仅当文本之前包含某些内容时,正则表达式才匹配
【发布时间】:2018-03-12 16:31:32
【问题描述】:

鉴于以下文字

KEYWORD This is a test
We want to match the following groups 1:YES 2:YES 3:YES

我想使用“1:YES”、“2:YES”和“3:YES”匹配

((\d):YES)

当且仅当全文中的第一个单词是“KEYWORD”

鉴于此测试:

This is a test
We want to match the following groups 1:YES 2:YES 3:YES

找不到匹配项

【问题讨论】:

  • 如果您显示您当前使用的 Java 代码,它可以使答案更简单(正则表达式和逻辑的组合)。
  • 看来你正在尝试做类似\A(?=KEYWORD)[\s\S]*?((?:\d:YES\s*)+)的事情
  • 如果您不尝试对所有内容都使用一个正则表达式,有时阅读起来会更容易、更清晰。您可以先匹配KEYWORD,然后匹配并提取所有其他组。

标签: java regex regex-lookarounds


【解决方案1】:

Java(与大多数正则表达式引擎一样)不支持无限长度查找,但是有一种解决方法!

String str = "KEYWORD This is a test\n" +
        "We want to match the following groups 1:YES 2:YES 3:YES";
Matcher matcher = Pattern.compile("(?s)(?<=\\AKEYWORD\\b.{1,99999})(\\d+:YES)").matcher(str);
while (matcher.find()) {
    System.out.println(matcher.group(1));
}

哪些输出:

1:YES
2:YES
3:YES

这里的诀窍是(?&lt;=\\AKEYWORD.{1,99999}) 背后的外观,它的长度很大(但不是无限的)。 (?s) 表示 DOTALL 标志(点也匹配换行符),\A 表示需要输入的开始,因为^ 匹配使用 DOTALL 标志时的行开始。

【讨论】:

  • \\d+ 周围的非捕获组实际上并不需要。此外,\b 可能在KEYWORD 之后使用很重要。不错的答案虽然 +1
  • @ctwheels 我想我会改进 OP 的正则表达式,它捕获了这个数字,但并没有停下来认为它是不需要的......呃。我添加了\b - 好主意。
【解决方案2】:

在不欺骗 Java 中的lookbhinds 的情况下,您可以使用\G 捕获\d+:YES\b 字符串。 \G 导致匹配从上一个匹配结束的地方开始,或者它将匹配与 \A 相同的字符串开头。

我们需要它的第一个功能:

(?:\AKEYWORD|\G(?!\A))[\s\S]*?(\d:YES\b)

细分:

  • (?:非捕获组开始
    • \A匹配主题字符串的开头
    • KEYWORD匹配关键字
    • |或者
    • \G(?!\A) 从上一场比赛结束的地方继续
  • )NCG 结束
  • [\s\S]*? 不贪婪地匹配其他任何东西
  • (\d+:YES\b) 匹配并捕获我们想要的部分

Live demo

Java 代码:

Pattern p = Pattern.compile("(?:\\AKEYWORD|\\G(?!\\A))[\\s\\S]*?(\\d+:YES\\b)");
Matcher m = p.matcher(string);                                   
while (m.find()) {
    System.out.println(m.group(1));
}

Live demo

【讨论】:

  • 同意,最好使用\G
猜你喜欢
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
相关资源
最近更新 更多