如果运行以下代码,我将获得false
,但如果我从Pattern.CASE_INSENSITIVE
删除Pattern.compile
,则结果为真
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());
}
知道发生了什么事吗?
答案 0 :(得分:8)
为什么这很奇怪?它正在按预期工作,可能是由于您作为2 nd 参数传递的标志。
让我们来看看你的模式: -
".*(?<!S)\\.a\\s*\\(\\s*\\)\\s*$"
您的模式将匹配S
之前没有.a
的字符串。从您的模式的下面部分可以清楚地看出这一点。
(?<!S)\\.a // Match if `.a` is not preceded by `S`.
现在,当您使用Pattern.CASE_INSENSITIVE
时,此条件会在s
之前检查S
和.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*$");
使用(?i)
的优势在于,您可以使用它只制作模式CASE_INSENSITIVE
的一部分。例如,如果您希望仅检查(?<!S)
,但以下字符串可以是.a
或.A
,那么您可以在(?i)
之前使用.a
}: -
Pattern p = Pattern.compile(".*(?<!S)(?i)\\.a\\s*\\(\\s*\\)\\s*$");
^^^
现在,(?i)
标记后的整个模式将以CASE_INSENSITIVE
方式匹配。
另外,请注意,您并不需要在评论中指出 look-behind 或不区分大小写匹配。如果您的信件只应为[^S]
,则只需使用[aA]
和a
即可。因为 look-behinds 和不区分大小写会带来一些性能差异。因此,您只需将模式更改为: -
Pattern p = Pattern.compile(".*[^S][.][aA][ ]*[(][ ]*[)][ ]*$");
我还用character class
替换了反斜杠。我更喜欢使用它,而不是双重转义元字符。但这只是一个品味问题。你可以随心所欲地使用它。