Pregunta ¿Qué es un límite de palabras en expresiones regulares?


Estoy usando expresiones regulares de Java en Java 1.6 (inter alia para analizar la salida numérica) y no puedo encontrar una definición precisa de \b ("límite de palabras"). Yo había supuesto que -12 sería una "palabra entera" (emparejado por \b\-?\d+\b) pero parece que esto no funciona. Estaría agradecido de saber cómo se pueden combinar los números separados por espacios.

Ejemplo:

Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*");
String plus = " 12 ";
System.out.println(""+pattern.matcher(plus).matches());
String minus = " -12 ";
System.out.println(""+pattern.matcher(minus).matches());
pattern = Pattern.compile("\\s*\\-?\\d+\\s*");
System.out.println(""+pattern.matcher(minus).matches());

Esto devuelve:

true
false
true

74
2017-08-24 20:46


origen


Respuestas:


Un límite de palabras, en la mayoría de los dialectos de expresiones regulares, es una posición entre \w y \W (char no de palabra), o al principio o al final de una cadena si comienza o termina (respectivamente) con un carácter de palabra ([0-9A-Za-z_])

Entonces, en la cuerda "-12", coincidiría antes del 1 o después del 2. El tablero no es un personaje de palabra.


56
2017-08-24 21:00



Un límite de palabras puede ocurrir en una de tres posiciones:

  1. Antes del primer caracter en la cadena, si el primer caracter es un personaje de palabra.
  2. Después del último carácter en la cadena, si el último carácter es un carácter de palabra.
  3. Entre dos caracteres en la cadena, donde uno es un carácter de palabra y el otro no es un carácter de palabra.

Los caracteres de Word son alfanuméricos; un signo menos no es. Tomado de Tutorial Regex.


17
2017-08-24 21:05



Consulte la documentación sobre las condiciones de contorno:

http://java.sun.com/docs/books/tutorial/essential/regex/bounds.html

Mira esta muestra:

public static void main(final String[] args)
    {
        String x = "I found the value -12 in my string.";
        System.err.println(Arrays.toString(x.split("\\b-?\\d+\\b")));
    }

Cuando lo imprima, observe que el resultado es el siguiente:

[Encontré el valor - en mi cadena]

Esto significa que el carácter "-" no se está recogiendo como estar en el límite de una palabra porque no se considera un carácter de palabra. Parece que @brianary me ganó un poco, así que recibe un voto positivo.


4
2017-08-24 21:03



Un límite de palabras es una posición que está precedida por un carácter de palabra y no seguido por uno, ni seguido de un carácter de palabra y no precedido por uno.


4
2017-08-25 01:36



Hablo de lo que \b-Los límites de expresiones regex estilo en realidad son aquí.

La historia corta es que son condicional. Su comportamiento depende de lo que están próximos.

# same as using a \b before:
(?(?=\w) (?<!\w)  | (?<!\W) )

# same as using a \b after:
(?(?<=\w) (?!\w)  | (?!\W)  )

A veces eso no es lo que quieres. Vea mi otra respuesta para la elaboración.


4
2017-11-18 13:35



Me encontré con un problema aún peor al buscar texto para 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 descubrí (resumido principalmente de http://www.regular-expressions.info, que es un gran sitio): en la mayoría de los sabores de expresiones regulares, los personajes que coinciden con la clase de personaje de mano corta \w son los personajes que son tratados como personajes de palabras por límites de palabras. Java es una excepción. Java es compatible con Unicode para \b pero no para \w. (Estoy seguro de que había una buena razón para eso en ese momento).

los \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, \wincluye muchos personajes 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.

Por eso, las búsquedas de expresiones regulares basadas en Java para C++, C# o .NET (incluso cuando recuerda escaparse del período y las ventajas) son atornilladas 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 esos idiomas con nombres extraños, debe reemplazar el \b con antes y 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));

PD Mi agradecimiento a http://regexpal.com/ sin quien el mundo regex sería muy miserable!


4
2017-12-16 16:54



Creo que su problema se debe al hecho de que - no es un personaje de palabra Por lo tanto, la palabra límite coincidirá después de la -, y entonces no lo capturará Los límites de palabras coinciden antes que el primero y después de los últimos caracteres de una cadena, así como cualquier lugar donde antes sea un carácter de palabra o un carácter que no sea una palabra, y después es lo contrario. También tenga en cuenta que el límite de palabras es una coincidencia de ancho cero.

Una posible alternativa es

(?:(?:^|\s)-?)\d+\b

Esto coincidirá con cualquier número que comience con un carácter de espacio y un guión opcional, y que termine en un límite de palabra. También coincidirá con un número que comienza al comienzo de la cadena.


1
2017-08-24 20:59



Creo que es el límite (es decir, el siguiente personaje) del último partido o el comienzo o el final de la cadena.


0
2017-08-24 20:55



cuando usas \\b(\\w+)+\\b eso significa coincidencia exacta con una palabra que contiene solo caracteres de palabras ([a-zA-Z0-9]) 

en su caso, por ejemplo, configuración \\b al comienzo de Regex aceptará -12(con espacio) pero nuevamente no aceptará -12(sin espacio)

como referencia para apoyar mis palabras: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html


0
2017-11-19 16:41



En el curso de aprender la expresión regular, estaba realmente atrapado en el metacarácter que es \b. De hecho, no comprendí su significado mientras me lo preguntaba "qué es, qué es"repetitivamente. Después de algunos intentos usando el sitio web, Observo los trazos verticales rosados ​​al comienzo de las palabras y al final de las palabras. Lo entendí bien en ese momento. Ahora es exactamente palabra(\w)-límite.

Mi punto de vista es meramente orientado a la comprensión. La lógica detrás de esto debe ser examinada a partir de otras respuestas.

enter image description here


0
2018-06-01 01:19