ทำไม String.split จึงต้องใช้ตัวคั่นไพพ์เพื่อหนี


140

ฉันกำลังพยายามแยกไฟล์ที่มีแต่ละบรรทัดด้วยค่าที่คั่นด้วยไพพ์ มันไม่ทำงานอย่างถูกต้องเมื่อฉันไม่ได้หนีตัวคั่นไปป์ด้วยวิธีแยก แต่ก็ทำงานได้อย่างถูกต้องหลังจากที่ฉันหนีไปป์ตามด้านล่าง

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

ใครช่วยอธิบายหน่อยได้split()ไหมว่าทำไมต้องมีการหลบหนีจากตัวละครในท่อ?


13
คำตอบด้านล่างตอบว่า "ทำไม" แต่เพียง FYI ถ้าคุณกำลังพยายามที่จะตรงกับสตริงตัวอักษรที่คุณอาจมองไปที่Pattern.quote มันใช้เวลาStringและส่งกลับ regex Stringที่จะตรงกับการป้อนข้อมูล (เช่นจะดูแลการหลบหนีทั้งหมดสำหรับคุณ)
yshavit

+1 สำหรับPattern.quote
redDevil

คำตอบ:


175

String.splitคาดว่าข้อโต้แย้งการแสดงออกปกติ unescaped |จะถูกแจงเป็น regex หมายถึง "สตริงว่างหรือสตริงว่าง" ซึ่งไม่ใช่สิ่งที่คุณหมายถึง


76

เนื่องจากไวยากรณ์สำหรับพารามิเตอร์ที่จะแยกเป็นนิพจน์ทั่วไปซึ่งใน '|' มีความหมายพิเศษของ OR และ '\ |' หมายถึงตัวอักษร '|' ดังนั้นสตริง "\\ |" หมายถึงการแสดงออกปกติ '\ |' ซึ่งหมายความว่าตรงกับอักขระ '|'


1
ขอบคุณสำหรับคำอธิบายนี้ ฉันมักจะลืมที่จะใช้การหลบหนีสองครั้ง ตอนนี้ฉันรู้แล้วว่าทำไมมันถึงเป็นอย่างนั้นมันก็จะช่วยให้ฉันจำได้ในภายหลัง
sufinawaz

จะเกิดอะไรขึ้นถ้าค่าของสายอักขระ String มีอักขระบางตัว? คุณจะแยกได้อย่างไรโดยไม่ต้องแยก escape \ pipe ?
AlexandreJ

@AlexandreJ คุณจะถามวิธีแยกบรรทัดที่มีลักษณะ: Some|Delimited|Text|With|An\|Embedded|Pipe|Charเป็น("Some", "Delimited", "Text", "With", "An\|Embedded", "Pipe", "Char")อย่างไร ฟังก์ชันแยกไม่สนับสนุนการหลบหนีเช่นนี้ แต่คุณอาจสามารถสร้างนิพจน์ทั่วไปที่จะใช้กับกรณีนี้ได้เช่นเดียวกับการยืนยันเชิงลบที่มีความกว้างเป็นศูนย์ดูหลังกลุ่ม: (?<!\\)\|ซึ่งจะเป็นline.split("(?<!\\\\)\\|");
dlamblin

6

คุณสามารถทำได้:

String[] arrayString = yourString.split("\\|");

คุณต้องหลบหนี \ เพื่อใช้คุณจะ regex "yourString.split (" \\ | ")" นั่นคือสูตรที่เหมาะสม
mautrok
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.