私のような言葉のテキストを検索するときにさらに悪化問題に遭遇した.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
ます。
これが、Javaベースの正規表現がを検索する理由C++
、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/に感謝します。これがないと、正規表現の世界は非常に悲惨です。