[java] \ R이 Java 8과 Java 9의 정규식에서 다르게 작동하는 이유는 무엇입니까?

다음 코드는 Java 8 및 9 모두에서 컴파일되지만 다르게 작동합니다.

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);
        }
    }
}

Java 8로 실행하면 다음이 반환됩니다.

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

그러나 Java 9로 실행하면 출력이 다릅니다.

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

왜?



답변

자바 문서는 유니 코드 표준을 준수 벗어났습니다. Javadoc \R은 일치해야하는 내용을 잘못 이해합니다 . 읽습니다.

\R 모든 유니 코드 줄 바꿈 시퀀스는 다음과 같습니다. \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

그 Java 문서는 버그가 있습니다. 그것에서 R1.6 줄 바꿈 섹션 정규 표현식에, 유니 코드 기술 표준 # 18 분명히 말한다 :

위에 나열된 모든 줄 끝 문자 및 시퀀스 (예 : # 1)를 일치시키기 위해 “\ R”과 같은 정규식 메타 문자가있는 것이 좋습니다. 이것은 다음 표현식과 동등한 것에 해당합니다. 이 표현은 백업을 피해야하기 때문에 약간 복잡합니다.

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

즉, 단지 두 개의 코드 포인트 CR + LF (캐리지 리턴 + 바꿈) 시퀀스를 일치시킬 수 그렇지 는 것을 제공되는 세트에서 단일 코드 포인트를 하지 후 바꿈 뒤에 만 단지 캐리지 리턴 . 백업이 허용되지 않기 때문입니다 . CRLF가 \R제대로 작동하려면 원자 적이어야합니다 .

따라서 Java 9는 더 이상 R1.6이 강력하게 권장하는 사항을 따르지 않습니다. 또한 Java 8에서는하지 말아야 할 일을하고 있고하지 말아야 할 일을하고 있습니다.

Sherman (읽기 : Xueming Shen)에게 다시 외칠 때가 된 것 같습니다. 나는 이전에 공식적인 적합성의 핵심적인 문제에 대해 그와 함께 일했습니다.


답변

Java 8의 버그 였고 수정되었습니다 : JDK-8176029 : “Linebreak matcher는 javadoc에 명시된 패턴과 동일하지 않습니다” .

참조 : Java-8 regex negative lookbehind with`\ R`


답변