2

我会得到一个falseif 运行以下代码,但如果我从中删除Pattern.CASE_INSENSITIVEPattern.compile结果为 true

public static void main(String[] args) {
    Pattern p = Pattern.compile(".*(?<!S)\\.a\\s*\\(\\s*\\)\\s*$", Pattern.CASE_INSENSITIVE);
    String s = "attributes.a()";
    Matcher m = p.matcher(s);
    System.out.println(m.matches());
}

知道发生了什么吗?

4

1 回答 1

8

为什么奇怪?它按预期工作,可能是由于您作为第二个参数传递的标志。

让我们看看你的模式: -

".*(?<!S)\\.a\\s*\\(\\s*\\)\\s*$"

您的模式将匹配没有Sbefore的字符串.a。从您的模式的以下部分可以清楚地看到这一点。

(?<!S)\\.a  // Match if `.a` is not preceded by `S`.

现在,当您使用 时Pattern.CASE_INSENSITIVE,此条件将同时检查sS,之前.a和如果其中任何一个存在,它将不匹配。所以你的模式从字面上变成: -

(?<![sS])\\.a  // Match if `.a` is not preceded by `S` or `s`.

现在,在你的字符串中: -

"attributes.a()"

你有小s.a。因此,您的代码中的模式将返回true此字符串,并启用不区分大小写标志。


仅供参考,您也可以使用(?i)标志而不是传递第二个参数Pattern.CASE_INSENSITIVE来查看相同的效果。所以下面的模式和你的一样:-

Pattern p = Pattern.compile("(?i).*(?<!S)\\.a\\s*\\(\\s*\\)\\s*$");

using 的好处(?i)是,你可以用它来制作你的 pattern 的一部分CASE_INSENSITIVE。例如,如果您希望只检查(?<!S),但以下字符串可以是.aor .A,那么您可以(?i)在之前使用.a:-

Pattern p = Pattern.compile(".*(?<!S)(?i)\\.a\\s*\\(\\s*\\)\\s*$");
                                      ^^^

现在,标志后的整个模式(?i)将以方式匹配CASE_INSENSITIVE


另外,请注意,正如评论中指出的那样,您实际上并不需要在这里进行后视或不区分大小写的匹配。如果你的信只应该是.你可以简单地[^S]使用. 因为后不区分大小写会带来一些性能差异。因此,您可以简单地将模式更改为: -[aA]a

Pattern p = Pattern.compile(".*[^S][.][aA][ ]*[(][ ]*[)][ ]*$");

我还将反斜杠替换为character class. 我更喜欢使用它,而不是双重转义元字符。但这只是口味问题。你可以使用任何你喜欢的东西。

于 2013-01-30T06:16:28.257 回答