Mengapa String.split membutuhkan pembatas pipa untuk melarikan diri?

140

Saya mencoba mengurai file yang memiliki setiap baris dengan nilai batas pipa. Itu tidak berfungsi dengan benar ketika saya tidak lolos dari pembatas pipa dalam metode split, tetapi itu bekerja dengan benar setelah saya lolos dari pipa seperti di bawah ini.

private ArrayList<String> parseLine(String line) {
    ArrayList<String> list = new ArrayList<String>();
    String[] list_str = line.split("\\|"); // note the escape "\\" here
    System.out.println(list_str.length);
    System.out.println(line);
    for(String s:list_str) {
        list.add(s);
        System.out.print(s+ "|");
    }
    return list;
}

Bisakah seseorang tolong jelaskan mengapa karakter pipa perlu melarikan diri untuk split()metode ini?

mulai ini
sumber
13
Jawaban di bawah ini menjawab "mengapa," tetapi hanya FYI, jika Anda mencoba untuk mencocokkan String literal Anda mungkin juga melihat Pattern.quote . Dibutuhkan Stringdan mengembalikan regex Stringyang akan cocok dengan input (yaitu, itu mengurus semua pelarian untuk Anda).
yshavit
+1 untukPattern.quote
redDevil

Jawaban:

175

String.splitmengharapkan argumen ekspresi reguler. Unescaped |diuraikan sebagai regex yang berarti "string kosong atau string kosong," yang bukan yang Anda maksud.

Louis Wasserman
sumber
76

Karena sintaks untuk parameter untuk dipecah adalah ekspresi reguler, di mana di '|' memiliki arti khusus OR, dan '\ |' berarti literal '|' jadi string "\\ |" berarti ungkapan reguler '\ |' yang artinya cocok persis dengan karakter '|'.

dlamblin
sumber
1
Terima kasih atas penjelasannya. Saya hampir selalu lupa menggunakan double escape. Sekarang saya tahu mengapa seperti itu, itu pasti akan membantu saya mengingat mulai sekarang.
sufinawaz
Apa yang terjadi jika nilai garis String memiliki beberapa karakter Pipa? Bagaimana Anda bisa membelah tanpa membelah pipa yang lolos \ | ?
AlexandreJ
@AlexandreJ Apakah Anda bertanya bagaimana membagi garis yang terlihat seperti: Some|Delimited|Text|With|An\|Embedded|Pipe|Charmenjadi ("Some", "Delimited", "Text", "With", "An\|Embedded", "Pipe", "Char")? Fungsi split tidak mendukung pelolosan seperti ini, tetapi Anda mungkin dapat membuat ekspresi reguler yang akan berfungsi untuk kasus ini, seperti dengan pernyataan negatif lebar nol yang terlihat di belakang grup: (?<!\\)\|yang manaline.split("(?<!\\\\)\\|");
dlamblin
6

Anda bisa melakukan ini:

String[] arrayString = yourString.split("\\|");
Ravinath
sumber
Anda harus melarikan diri dari \ untuk menggunakan Anda regex "yourString.split (" \\ | ")" itu formula yang tepat.
mautrok