【问题标题】:Negative lookup behind not working as expected未按预期工作背后的负查找
【发布时间】:2018-04-12 08:34:32
【问题描述】:

如果它出现在 ex 之后,我不想提取值。

高达 12 GB ->

12GB -> 12GB

正则表达式 -> (?i)(?<!up\s{1}to\s{1})([0-9]{1,})\s*(GB|MB|KB)

输入 -> up to 12 gb output -> 2 gb(非预期)

      up to 1 gb output ->        (expected)

我不知道它是如何为第一个输入获得 2 GB 的

【问题讨论】:

  • (OT:{1} 完全是多余的,+{1,} 相同,但更常用且更易于阅读。)
  • 您可以使用:(?i)(?<!up\sto\s)\b\d+\s*[GMK]B
  • 使用(?i)\b(?<!\bup\sto\s)\d+\s*[GMK]B
  • @AdrienBrunelat 这对我来说似乎很清楚。 Malav 对为什么他们给出的正则表达式匹配 2 而不是来自 up to 12 gb12 感到困惑。
  • 坦率地说,我也很困惑。我本来希望第一个捕获组也匹配 12

标签: java regex regex-negation regex-lookarounds


【解决方案1】:

(?i)(?<!up\s{1}to\s{1})([0-9]{1,})\s*(GB|MB|KB) regex matches 2 gb in 12 gb 因为在1 字符位置的匹配失败(因为它前面有up to ,但是,由于正则表达式引擎继续在字符串中查找匹配,它在下一个匹配位置,在1 之后。

您可以将匹配“锚定”在单词边界(\b)或非数字后的位置((?<![0-9])),例如(?i)\b(?<!\bup\sto\s)\d+\s*[GMK]B,但如果up to和数字之间有0个或多个空格,它将不起作用。

使用constrained width lookbehind 允许在后视中使用{min,max) 限制量词:

String pat = "(?i)\\b(?<!\\bup\\s{0,100}to\\s{0,100})\\d+\\s*[GMK]B\\b";

Java demo

List<String> strs = Arrays.asList("up to 1 gb output", "up to 1gb output", "up   to1 gb output", "1 gb output");
Pattern p = Pattern.compile("(?i)\\b(?<!\\bup\\s{0,100}to\\s{0,100})\\d+\\s*[GMK]B\\b");
for (String str : strs) {
    Matcher m = p.matcher(str);
    while (m.find()) {
        System.out.println(str + ": " + m.group(0));
    }
}

输出

1 gb output: 1 gb

模式详情

  • (?i) - 不区分大小写的修饰符
  • \\b - 单词边界
  • (?&lt;!\\bup\\s{0,100}to\\s{0,100}) - 在当前位置的左侧,不能有一个完整的单词 up 后跟 0 到 100 个空格,然后是 to,然后是 0 到 100 个空格
  • \\d+ - 1+ 位(替换为 \\d[\\d.]* 以匹配浮点数) \\s* - 0+ 个空格
  • [GMK]B - GBMBKB
  • \\b - 字边界。

注意:将\b 字边界放在模式的开头,可以提高效率,因为在测试字边界之前无需检查整个后向模式。

【讨论】:

  • 非常感谢您的详细解释。但是我在使用它时得到了这个。它不会接受 {m, n} {0,100} 后视内的量词使其宽度不固定
  • @Malav 见ideone.com/QpFOeY。你在哪里看到这个警告?甚至 Java 正则表达式在线测试人员都说it is OK
  • @Malav 您是否意识到您正在 PCRE 测试仪中测试 Java 正则表达式?为什么???请不要混合正则表达式口味。如果您希望它在 Java 中工作,请使用 Java 兼容工具。
  • @Malav 同样,如果您喜欢在线正则表达式测试器,请参阅regexplanet.com/share/index.html?share=yyyyyegmvyr
  • @Malav 我已经编写了您可以复制/粘贴的代码。
【解决方案2】:

您可以将此正则表达式与否定的lookbehind和单词边界一起使用:

(?i)(?<!up\sto\s)\b\d+\s*[GMK]B

RegEx Demo

\b 在这里很重要,以确保不会在 1 位或更多位之前断言后向表达式。

还要记住\s{1}\s 相同。

【讨论】:

  • 如果数字前有2个空格,仍然会提取数字。
  • @anubhava 但是后面的lookuo使用固定宽度。如果我在“up”/“to”之后有多个空格/零空格我应该如何处理它
  • @Malav:你没有在你的问题中提到关于多个空格的要求,你的正则表达式有 (?&lt;!up\s{1}to\s{1}) 这意味着只有一个空格。
  • 我应该提到这一点。但是基本案例对我不起作用,所以发布了。
  • 用一个空格替换所有多个空格然后应用这个正则表达式更容易,例如str = str.replaceAll("\\s{2,}", " ");
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 2012-10-28
  • 1970-01-01
  • 2012-11-13
  • 2015-06-03
  • 2019-10-24
  • 2018-04-06
  • 1970-01-01
相关资源
最近更新 更多