负查找背后没有按预期工作

Negative lookup behind not working as expected

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

最多 12 GB ->

12 GB -> 12 GB

正则表达式 -> (?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 的

您可以将此正则表达式与负向回顾和词边界一起使用:

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

RegEx Demo

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

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

(?i)(?<!up\s{1}to\s{1})([0-9]{1,})\s*(GB|MB|KB) regex matches 2 gb in 12 gb 因为 lookbehind 在 1 字符位置匹配失败(因为它前面有 up to ,但是,因为正则表达式引擎继续在里面找到匹配字符串,它在 1.

之后的下一个位置匹配

您可以 "anchor" 在单词边界(使用 \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 - 单词边界
  • (?<!\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 单词边界放在模式的开头,可以提高效率,因为在测试单词边界之前无需检查整个后视模式。