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

El siguiente código se comstack 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é?

La documentación de Java está fuera de conformidad con el estándar de Unicode. El Javadoc empaña lo que se supone que debe coincidir con \R Se lee:

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

Esa documentación de Java está llena de errores. En su sección sobre R1.6 Saltos de línea, el Estándar Técnico Unicode # 18 sobre Expresiones Regulares establece claramente:

Se recomienda encarecidamente que haya un meta-carácter de expresión regular, como “\ R”, para hacer coincidir todos los caracteres y secuencias de finalización de línea enumerados anteriormente (por ejemplo, en # 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{DA}|(?!\u{DA})[\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 + salto de línea) o bien un solo punto de código de ese conjunto siempre que no sea solo un retorno de carro solo que luego sea seguido de un salto de línea . Eso es porque no está permitido hacer una copia de seguridad . CRLF debe ser atómico para que \R funcione correctamente.

Así que Java 9 ya no cumple con 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 que le dé a Sherman (lea: Xueming Shen) un grito de nuevo. He trabajado con él antes en estos asuntos esenciales de conformidad formal.

Fue un error en Java 8 y se solucionó: JDK-8176029: “El comparador de Linebreak no es equivalente al patrón como se indica en javadoc” .

También vea: Java-8 regex negativo lookdhind with `\ R`