.NET
、、、、などの単語をテキストで検索すると、さらに悪い問題が発生しましC++
た。コンピュータープログラマーは、正規表現を書くのが難しい言語に名前を付けるよりもよく知っていると思うでしょう。C#
C
とにかく、これは私が見つけたものです(主にhttp://www.regular-expressions.infoから要約されています。これは素晴らしいサイトです):正規表現のほとんどのフレーバーでは、短縮文字クラスと一致する文字\w
は単語の境界によって単語文字として扱われる文字。Javaは例外です。JavaはUnicodeをサポートしていますが、はサポートして\b
いません\w
。(当時、それには正当な理由があったと確信しています)。
「単語文字」の\w
略です。常にASCII文字と一致し[A-Za-z0-9_]
ます。アンダースコアと数字が含まれていることに注意してください(ただし、ダッシュは含まれていません)。Unicodeをサポートするほとんどのフレーバーに\w
は、他のスクリプトの多くの文字が含まれています。どのキャラクターが実際に含まれるかについては、多くの矛盾があります。アルファベットの文字や表意文字からの文字や数字が一般的に含まれています。数字ではないアンダースコアおよび数字記号以外のコネクタ句読点は、含まれる場合と含まれない場合があります。XMLスキーマとXPathには、すべてのシンボルが含まれてい\w
ます。ただし、Java、JavaScript、およびPCREは、ASCII文字とのみ一致し\w
ます。
C++
これが、Javaベースの正規表現が、、C#
または.NET
(ピリオドとプラスをエスケープすることを覚えている場合でも)を検索する理由です\b
。
注:文末のピリオドの後に誰かがスペースを入れなかった場合など、テキストの間違いをどうすればよいかわかりません。私はそれを許可しましたが、それが必ずしも正しいことであるかどうかはわかりません。
とにかく、Javaでは、これらの奇妙な名前の言語のテキストを検索する場合は、\b
空白と句読点の指定子の前後をに置き換える必要があります。例えば:
public static String grep(String regexp, String multiLineStringToSearch) {
String result = "";
String[] lines = multiLineStringToSearch.split("\\n");
Pattern pattern = Pattern.compile(regexp);
for (String line : lines) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
result = result + "\n" + line;
}
}
return result.trim();
}
次に、テストまたはメイン機能で:
String beforeWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|^)";
String afterWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|$)";
text = "Programming in C, (C++) C#, Java, and .NET.";
System.out.println("text="+text);
// Here is where Java word boundaries do not work correctly on "cutesy" computer language names.
System.out.println("Bad word boundary can't find because of Java: grep with word boundary for .NET="+ grep("\\b\\.NET\\b", text));
System.out.println("Should find: grep exactly for .NET="+ grep(beforeWord+"\\.NET"+afterWord, text));
System.out.println("Bad word boundary can't find because of Java: grep with word boundary for C#="+ grep("\\bC#\\b", text));
System.out.println("Should find: grep exactly for C#="+ grep("C#"+afterWord, text));
System.out.println("Bad word boundary can't find because of Java:grep with word boundary for C++="+ grep("\\bC\\+\\+\\b", text));
System.out.println("Should find: grep exactly for C++="+ grep(beforeWord+"C\\+\\+"+afterWord, text));
System.out.println("Should find: grep with word boundary for Java="+ grep("\\bJava\\b", text));
System.out.println("Should find: grep for case-insensitive java="+ grep("?i)\\bjava\\b", text));
System.out.println("Should find: grep with word boundary for C="+ grep("\\bC\\b", text)); // Works Ok for this example, but see below
// Because of the stupid too-short cutsey name, searches find stuff it shouldn't.
text = "Worked on C&O (Chesapeake and Ohio) Canal when I was younger; more recently developed in Lisp.";
System.out.println("text="+text);
System.out.println("Bad word boundary because of C name: grep with word boundary for C="+ grep("\\bC\\b", text));
System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
// Make sure the first and last cases work OK.
text = "C is a language that should have been named differently.";
System.out.println("text="+text);
System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
text = "One language that should have been named differently is C";
System.out.println("text="+text);
System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
//Make sure we don't get false positives
text = "The letter 'c' can be hard as in Cat, or soft as in Cindy. Computer languages should not require disambiguation (e.g. Ruby, Python vs. Fortran, Hadoop)";
System.out.println("text="+text);
System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
PS http://regexpal.com/に感謝します。これがないと、正規表現の世界は非常に悲惨なものになります。