なぜそれは奇妙ですか?おそらく2番目の引数として渡したフラグが原因で、意図したとおりに機能しています。
あなたのパターンを見てみましょう: -
".*(?<!S)\\.a\\s*\\(\\s*\\)\\s*$"
Sあなたのパターンは、 beforeを持たない文字列と一致します.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)参考までに、2 番目のパラメーターを渡す代わりにフラグを使用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ます。
また、コメントで指摘されているように、ここでは後読みまたは大文字と小文字を区別しない一致は実際には必要ないことに注意してください。あなた[^S]の[aA]手紙がa. 後読みと大文字と小文字の区別がないため、パフォーマンスに多少の違いが生じるからです。したがって、パターンを次のように変更するだけです。
Pattern p = Pattern.compile(".*[^S][.][aA][ ]*[(][ ]*[)][ ]*$");
バックスラッシュも に置き換えましたcharacter class。メタ文字を二重にエスケープする代わりに、それを使用することを好みます。しかし、それは単なる好みの問題です。好きなものを使用できます。