积极的后视行为不正确

positive lookbehind not behaving correctly

正后视的代码片段如下

public class PositiveLookBehind {
    public static void main(String[] args) {
        String regex = "[a-z](?<=9)";
        String input = "a9es m9x us9s w9es";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        System.out.println("===starting====");
        while(matcher.find()) {
            System.out.println("found:"+matcher.group()
            +" start index:"+matcher.start()
            +" end index is "+matcher.end()); 
        }
        System.out.println("===ending=====");
    }
}

我原以为我应该有 4 个匹配项,但令我惊讶的是输出显示没有匹配项。

谁能指出我的错误?

据我了解,这里的正则表达式是字母表,前面是数字 9,在 4 个位置都满足。

您当前的模式:[a-z](<=9) 表示:匹配小写字母并确保 position 紧跟字母 9,这是矛盾的.

如果要匹配以 9 开头的字母,请使用:(<=9)[a-z],这意味着:确保前面是 9,如果是,则匹配小写字母。

问题

请注意 (?<=9) 位于 [a-z] 之后。这是什么意思?

让我们考虑 "a9c" 这样的数据。

在开始时正则表达式引擎将其 "cursor" 放在它迭代的字符串的开头,这里:

|a9c
^-regex cursor is here

然后正则表达式引擎试图匹配正则表达式模式的每个部分从左到右。因此,在 [a-z](?<=9) 的情况下,它首先会尝试为 [a-z] 找到匹配项,在成功找到它的匹配项后,它将尝试移动到 (?<=9) 部分的评估。

因此 [a-z] 的匹配将发生在这里:

a9c
*<-- match for `[a-z]`

匹配正则表达式后,光标将移至此处:

a|9c *^--- 正则表达式引擎游标 ^---- 匹配 [a-z]

所以现在 (?<=9) 将被评估(注意光标的位置 |)。 (?<=subregex) 检查在光标之前是否存在可以被 subregex 匹配的文本。但是这里因为游标直接在 a (?<=9) 之后,look-behind "sees"/includes that a 作为子表达式应该测试的数据。但由于 a 无法与 9 匹配,因此评估失败。

解决方案

您可能想检查 9 是否放在 之前 可接受的字母。为此,您可以通过多种方式修改正则表达式:

  • with [a-z](?<=9.) 你做回溯测试 两个 前面的字符

    a9c|
     ^^
     9. - `9` matches 9, `.` matches any character (one directly before cursor)
    
  • 或更简单的 (?<=9)[a-z] 首先查找 9 然后查找 [a-z] 如果光标位于,这将使正则表达式匹配 9c 9|c.