2011-05-12 15 views
12

Tengo un patrón de expresiones regulares de Java y una oración que me gustaría combinar por completo, pero para algunas oraciones falla erróneamente. ¿Por qué es esto? (Para simplificar, no voy a utilizar mi complejo de expresiones regulares, pero sólo "*.")Java regex siempre falla

System.out.println(Pattern.matches(".*", "asdf")); 
System.out.println(Pattern.matches(".*", "[11:04:34] <@Aimbotter> 1 more thing")); 
System.out.println(Pattern.matches(".*", "[11:04:35] <@Aimbotter> Dialogue: 0,0:00:00.00,0:00:00.00,Default,{Orginal LV,0000,0000,0000,,[???]??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????} ")); 
System.out.println(Pattern.matches(".*", "[11:04:35] <@Aimbotter> Dialogue: 0,0:00:00.00,0:00:00.00,Default,{Orginal LV,0000,0000,0000,,[???]????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????} ")); 

Salida:

true 
true 
true 
false 

Tenga en cuenta que la cuarta frase contiene 10 caracteres de control Unicode \ u0085 en el medio los signos de interrogación, que no se muestran con fuentes normales. ¡Las oraciones tercera y cuarta en realidad contienen la misma cantidad de caracteres!

+0

Esto es especialmente extraño, porque Java es un motor de expresiones regulares Unicode ... –

+0

Sería peor si Java no sabría de las terminaciones de línea Unicode (http://www.fileformat.info/info/unicode/char /85/index.htm) – rurouni

+0

... @ tchrist pronto estará cerca y cuéntanos sobre qué tan roto está el motor de regex de Java. – aioobe

Respuesta

13

uso

Pattern.compile(".*",Pattern.DOTALL) 

si lo desea. para unir los personajes de control. Por defecto, solo coincide con los caracteres imprimibles.

De JavaDoc:

"En el modo dotall, la expresión coincide con cualquier carácter, incluyendo un final de línea Por defecto esta expresión no coincide con las terminaciones de línea

modo dotall también se puede activar a través de la... expresión bandera embebido (La s es una regla mnemotécnica para el modo "de una sola línea", que es lo que se llama en Perl.)"

Código de patrón (no es su \ u0085) (s?):.

/** 
* Implements the Unicode category ALL and the dot metacharacter when 
* in dotall mode. 
*/ 
static final class All extends CharProperty { 
boolean isSatisfiedBy(int ch) { 
    return true; 
} 
} 

/** 
* Node class for the dot metacharacter when dotall is not enabled. 
*/ 
static final class Dot extends CharProperty { 
boolean isSatisfiedBy(int ch) { 
    return (ch != '\n' && ch != '\r' 
       && (ch|1) != '\u2029' 
       && ch != '\u0085'); 
    } 
} 
+0

Gracias, (?) Trabajó. No probé Pattern.DOTALL porque tengo una tonelada de patrones compilados diferentes, y solo tuve que usar (? S) una vez (en una constante de cadena que incluí en la mayoría de los patrones). –

4

La respuesta está en la pregunta: 10 caracteres de control Unicode \ u0085

caracteres de control Unicode enviaban reconocidos por igual * \ n

1

El problema es que yo creo \ u0085 representa un salto de línea.. Si desea la coincidencia de líneas múltiples, debe usar Pattern.MULTILINE o Pattern.DOTALL. No es el hecho de que es Unicode - '\ n' también fallaría.

utilizarlo: Pattern.compile(regex, Pattern.DOTALL).matcher(input).matches()

2

Unicode/u0085 es una línea nueva, por lo que debe agregar (?s) - punto coincide con todos - al comienzo de su expresión regular o agregar el indicador al compilar la expresión regular.

Pattern.matches("(?s).*", "blahDeBlah\u0085Blah") 
+1

No '(? M)' - El modo multilínea significa que '^' y '$' coinciden al inicio/final de las líneas. Quiere '(? S)' para el modo de línea simple. Sí, es confuso (la idea es "tratar la entrada completa como si fuera una sola línea"). –

+0

Vaya, está en lo correcto señor. Fijo. –

Cuestiones relacionadas