Pertanyaan Mengapa \ R berperilaku berbeda dalam ekspresi reguler antara Java 8 dan Java 9?


Kode berikut mengkompilasi di kedua Java 8 & 9, tetapi berperilaku berbeda.

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

Ketika saya menjalankannya dengan Java 8 ia mengembalikan:

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

Tetapi ketika saya menjalankannya dengan Java 9, hasilnya berbeda:

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

Mengapa?


76
2017-12-18 15:53


asal


Jawaban:


Itu Dokumentasi Java tidak sesuai dengan Standar Unicode. Javadoc mengira apa \R seharusnya cocok. Bunyinya:

\R   Urutan linebreak Unicode apa pun, setara dengan \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Dokumentasi Java itu buggy. Dalam nya bagian tentang R1.6 Line Breaks, Unicode Technical Standard # 18 tentang Regular Expressions dengan jelas menyatakan:

Sangat disarankan agar ada meta-karakter ekspresi reguler, seperti "\ R", untuk mencocokkan semua karakter dan urutan akhir baris yang tercantum di atas (misalnya, dalam # 1). Ini akan sesuai dengan sesuatu yang setara dengan ekspresi berikut. Ekspresi itu sedikit rumit dengan kebutuhan untuk menghindari pencadangan.

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

Dengan kata lain, itu hanya bisa cocok dengan dua kode-titik CR + LF (carriage return + linefeed) urutan atau satu kode-poin dari set itu asalkan demikian tidak hanya carriage return saja yang kemudian diikuti oleh linefeed. Itu karena itu tidak diizinkan untuk dicadangkan. CRLF harus menjadi atom untuk \R berfungsi dengan benar.

Jadi Java 9 tidak lagi sesuai dengan rekomendasi R1.6. Selain itu, sekarang melakukan sesuatu yang seharusnya TIDAK dilakukan, dan tidak dilakukan, di Jawa 8.

Sepertinya sudah waktunya bagi saya untuk memberikan Sherman (baca: Xueming Shen) berteriak lagi. Saya telah bekerja dengan dia sebelumnya tentang hal-hal yang seluk-beluk dari kesesuaian formal.


46
2017-12-19 02:28



Itu bug di Java 8 dan diperbaiki: JDK-8176029: "Linebreak matcher tidak setara dengan pola seperti yang dinyatakan dalam javadoc".

Juga lihat: Java-8 regex negative lookbehind dengan `\ R`


63
2017-12-18 16:11