2017-12-18 3 views
76

다음 코드는 Java 8 & 9 모두에서 컴파일되지만 다르게 동작합니다.왜 R은 Java 8과 Java 9 사이의 정규식에서 다르게 동작합니까?

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

을하지만 자바 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); 
     } 
    } 
} 

내가 자바 8을 실행하면 반환

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

이유는 무엇입니까?

+3

Java 8에서와 같이 보입니다. 'R'은 욕심이 많지만 9에서는 그렇지 않습니다. – doublep

+0

'System.getProperty ("line.separator")'에서 얻은 문자열은 무엇입니까? – dasblinkenlight

+2

@ dasblinkenlight : 그건 중요하지 않아요. '\ R'는 [linebreak matcher] (https://docs.oracle.com/javase/9/docs/api/java/util/regex/Pattern.html)입니다. 그것은 OP가 가지고있는 것은 무엇이든 일치 할 것입니다. – Makoto

답변

46

Java documentation은 유니 코드 표준을 준수 벗어났습니다. Javadoc은 \R과 (과) 일치하는 것으로 착각합니다. 그것은 읽

\R 유니 코드 LINEBREAK 순서는, Java 문서는 버그가 있음을 \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

에 해당합니다. 그 section on R1.6 Line Breaks, Unicode Technical Standard #18 on Regular Expressions에서 명확하게 진술한다 :

강력하게 (예를 들어, # 1 위에 나열된 문자 시퀀스를 끝나는 모든 라인을 일치를 들면, "\의 R"로, 정규 표현식 메타 문자가있을 것을 권장합니다). 이것은 다음 표현식에 해당하는 것과 같습니다. 그 표현은 백업을 피할 필요가 있기 때문에 약간 복잡합니다.

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

은 즉, 만 그렇지 해당 세트에서 단일 코드 포인트가 있는지 제공된 두 개의 코드 포인트 CR + LF (캐리지 리턴 + 바꿈) 시퀀스를 일치시킬 이 아니고 인 경우 캐리지 리턴 만 입력하면 줄 바꿈이옵니다. 은 백업 할 수 없으므로입니다. \R이 제대로 작동하려면 CRLF가 원자 적이어야합니다.

Java 9는 더 이상 R1.6이 권장하는 내용을 더 이상 따르지 않습니다. 또한, 이제는 Java 8에서 수행하지 않았으며 수행하지 않은 작업을 수행 중입니다.

Sherman (Xueming Shen 읽음)에게 다시 소리 쳐야 할 때가 된 것 같습니다. 나는 공식적인 적합성에 관한이 핵심적인 문제에 관해 그와 함께 일해 왔습니다.

+1

해결 방법은'\\ R' 대신'(?> \\ R)'또는'\\ R {1} +'을 사용하거나 OP의 특정 경우에'\\ R {2 } \'R \\ R' 대신에'\\ R '을 사용하십시오. 흥미롭게도, '\\ R {1} \\ R {1}'또는'\\ R {2}'는 Java 9에서 원하는 결과를 제공하지 못합니다. 역 추적을 사용하지 않습니다. – Holger

+0

[JDK-8176983] (https://bugs.openjdk.java.net/browse/JDK-8176983)으로 수정 될 수 있습니까? – nullpointer

63
+7

자바 8 행동이 더 건강 해 보인다. "\ r \ n"을 두 개의 연속적인 줄 바꿈으로 해석하는 것은 가능하지만, 알다시피 그것은 거의 이해가되지 않습니다. 두 줄의 줄 바꿈을 의미하는 경우 "\ n \ n"또는 "\ r \ n \ r \ n"등, 즉 두 개의 * 같은 * 줄 바꿈을 써야합니다. "\ r \ n"은 실제로 하나만 의미해야합니다. – doublep

+2

그것은 이해가된다!. 그러나 자바 8은 내가 필요한 행동을했다. mmmh. –

+3

@ GermánBouzas : 먼저 줄 바꿈을 표준화해야한다고 생각합니다. 'replaceAll ("\\ R", "\\ n")'(테스트하지 않았지만 백 트랙 변경은 여기서 어떤 역할도하지 않을 것이라고 생각합니다. – doublep

관련 문제