Tôi chạy vào một vấn đề còn tồi tệ hơn khi tìm kiếm văn bản cho chữ thích .NET
, C++
, C#
, và C
. Bạn sẽ nghĩ rằng các lập trình viên máy tính sẽ biết nhiều hơn là đặt tên cho một ngôn ngữ khó viết các cụm từ thông dụng.
Dù sao, đây là những gì tôi phát hiện ra (được tóm tắt chủ yếu từ http://www.THER-expressions.info , một trang web tuyệt vời): Trong hầu hết các hương vị của regex, các ký tự được khớp với lớp nhân vật tay ngắn \w
là các ký tự được coi là ký tự từ theo ranh giới từ. Java là một ngoại lệ. Java hỗ trợ Unicode cho \b
nhưng không cho \w
. (Tôi chắc chắn rằng có một lý do tốt cho nó tại thời điểm đó).
Chữ \w
viết tắt của "từ nhân vật". Nó luôn khớp với các ký tự ASCII [A-Za-z0-9_]
. Lưu ý sự bao gồm của dấu gạch dưới và chữ số (nhưng không phải dấu gạch ngang!). Trong hầu hết các hương vị hỗ trợ Unicode, \w
bao gồm nhiều ký tự từ các tập lệnh khác. Có rất nhiều sự không nhất quán về các nhân vật thực sự được bao gồm. Các chữ cái và chữ số từ các chữ viết và chữ tượng hình thường được bao gồm. Dấu chấm câu kết nối khác với dấu gạch dưới và ký hiệu số không phải là chữ số có thể hoặc không bao gồm. Lược đồ XML và XPath thậm chí bao gồm tất cả các biểu tượng trong \w
. Nhưng Java, JavaScript và PCRE chỉ khớp với các ký tự ASCII \w
.
Đó là lý do dựa trên nền Java tìm kiếm regex cho C++
, C#
hoặc .NET
(ngay cả khi bạn nhớ để thoát khỏi giai đoạn và pluses) được bắt vít vào \b
.
Lưu ý: Tôi không biết phải làm gì về các lỗi trong văn bản, như khi ai đó không đặt dấu cách sau một khoảng thời gian ở cuối câu. Tôi đã cho phép, nhưng tôi không chắc chắn rằng đó là điều đúng đắn phải làm.
Dù sao, trong Java, nếu bạn đang tìm kiếm văn bản cho các ngôn ngữ có tên kỳ lạ đó, bạn cần thay thế \b
bằng trước và sau các chỉ định khoảng trắng và dấu chấm câu. Ví dụ:
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();
}
Sau đó, trong bài kiểm tra hoặc chức năng chính của bạn:
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 Tôi cảm ơn http://regapidal.com/ mà không có ai, thế giới regex sẽ rất đau khổ!