负查找背后没有按预期工作
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
\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
- GB
、MB
或 KB
\b
- 单词边界。
注意:将 \b
单词边界放在模式的开头,可以提高效率,因为在测试单词边界之前无需检查整个后视模式。
如果它出现在 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
\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
-GB
、MB
或KB
\b
- 单词边界。
注意:将 \b
单词边界放在模式的开头,可以提高效率,因为在测试单词边界之前无需检查整个后视模式。