me encontré con un problema aún peor cuando la búsqueda de texto de palabras como .NET
, C++
, C#
, y C
. Uno pensaría que los programadores de computadoras sabrían mejor que nombrar un idioma para el cual es difícil escribir expresiones regulares.
De todos modos, esto es lo que he descubierto (que se resumen en su mayoría de http://www.regular-expressions.info, que es un gran sitio): En la mayoría de los sabores de expresiones regulares, caracteres que se corresponden con la clase de caracteres taquigrafía \w
son los personajes que se tratan como personajes de palabras por límites de palabras. Java es una excepción. Java admite Unicode para \b
pero no para \w
. (Estoy seguro de que había una buena razón para eso en ese momento).
El \w
significa "carácter de palabra". Siempre coincide con los caracteres ASCII [A-Za-z0-9_]
. Observe la inclusión del guión bajo y los dígitos (¡pero no el guión!). En la mayoría de los sabores que admiten Unicode, \w
incluye muchos caracteres de otros scripts. Hay mucha inconsistencia acerca de qué personajes están realmente incluidos. Por lo general, se incluyen letras y dígitos de scripts alfabéticos e ideogramas. La puntuación del conector que no sea el guión bajo y los símbolos numéricos que no son dígitos pueden o no estar incluidos. XML Schema y XPath incluso incluyen todos los símbolos en \w
. Pero Java, JavaScript y PCRE solo coinciden con los caracteres ASCII con \w
.
¿Cuál es la razón de Java basada en búsquedas de expresiones regulares para C++
, C#
o .NET
(incluso cuando se recuerda a escapar del período y ventajas) están atornillados por el \b
.
Nota: No estoy seguro de qué hacer con los errores en el texto, como cuando alguien no pone un espacio después de un punto al final de una oración. Lo permití, pero no estoy seguro de que sea necesariamente lo correcto.
De todos modos, en Java, si está buscando texto para los idiomas con nombres extraños, debe reemplazar el \b
con el antes y el después del espacio en blanco y los designadores de puntuación. Por ejemplo:
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();
}
Luego, en su prueba o función principal:
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));
P. S. ¡Gracias a http://regexpal.com/ sin el cual el mundo regex sería muy miserable!
¿se puede poner un pequeño ejemplo con entrada y salida esperada? –
Intentaremos construir uno –
Ejemplo \t Patrón de patrón = Pattern.compile ("\\ s * \\ b \\ -? \\ d + \\ s *"); \t String plus = "12"; \t System.out.println ("" + pattern.matcher (plus) .matches()); \t Cadena minus = "-12"; \t System.out.println ("" + pattern.matcher (menos) .matches()); \t pattern = Pattern.compile ("\\ s * \\ -? \\ d + \\ s *"); \t System.out.println ("" + pattern.matcher (menos) .matches()); gives: true false true –