Pregunta ¿Por qué \ R se comporta de manera diferente en expresiones regulares entre Java 8 y Java 9?


El siguiente código se compila en Java 8 y 9, pero se comporta de manera diferente.

class Simple {
    static String sample = "\nEn un lugar\r\nde la Mancha\nde cuyo nombre\r\nno quiero acordarme";

    public static void main(String args[]){
        String[] chunks = sample.split("\\R\\R");
        for (String chunk: chunks) {
            System.out.println("Chunk : "+chunk);
        }
    }
}

Cuando lo ejecuto con Java 8, devuelve:

Chunk : 
En un lugar
de la Mancha
de cuyo nombre
no quiero acordarme

Pero cuando lo ejecuto con Java 9 la salida es diferente:

Chunk : 
En un lugar
Chunk : de la Mancha
de cuyo nombre
Chunk : no quiero acordarme

¿Por qué?


76
2017-12-18 15:53


origen


Respuestas:


los Documentación de Java está fuera de conformidad con el estándar Unicode. El Javadoc se equivoca \R se supone que coincida. Se lee:

\R   Cualquier secuencia de salto de línea Unicode, es equivalente a \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Que la documentación de Java tiene errores. En su sección sobre Salidas de línea R1.6, Norma técnica n.º 18 de Unicode sobre expresiones regulares claramente dice:

Se recomienda encarecidamente que haya un metacaraculo de expresión regular, como "\ R", para hacer coincidir todos los caracteres y secuencias de final de línea enumerados anteriormente (por ejemplo, en el n. ° 1). Esto correspondería a algo equivalente a la siguiente expresión. Esa expresión es un poco complicada por la necesidad de evitar la copia de seguridad.

 (?:\u{D A}|(?!\u{D A})[\u{A}-\u{D}\u{85}\u{2028}\u{2029}]

En otras palabras, solo puede coincidir con una secuencia de dos puntos de código CR + LF (retorno de carro + avance de línea) si no un único punto de código de ese conjunto siempre que sea no solo un retorno de carro solo que luego es seguido por un salto de línea. Eso es porque es no se permite hacer una copia de seguridad. CRLF debe ser atómico para \R para funcionar correctamente

Por lo tanto, Java 9 ya no se ajusta a lo que recomienda R1.6. Además, ahora está haciendo algo que se suponía que NO debía hacer, y no hizo, en Java 8.

Parece que es hora de darle a Sherman (léase: Xueming Shen) un grito nuevamente. He trabajado con él antes en estos asuntos esenciales de conformidad formal.


46
2017-12-19 02:28



Fue un error en Java 8 y se solucionó: JDK-8176029: "Linebreak matcher no es equivalente al patrón como se indica en javadoc".

Ver también: Java-8 regex negative lookbehind con `\ R`


63
2017-12-18 16:11