ก่อนอื่นมาสรุปการใช้งานของทั้งสาม:
・ แทนที่ (เป้าหมาย Charsequence, การแทนที่ Chareespence) , แทนที่เป้าหมายทั้งหมดด้วยการเปลี่ยนพารามิเตอร์ทั้งสองเป็นสตริง
・ replaceall (regex สตริง, การเปลี่ยนสตริง) , แทนที่การจับคู่ regex ทั้งหมดด้วยการเปลี่ยน เห็นได้ชัดว่า Regex เป็นนิพจน์ทั่วไปการเปลี่ยนเป็นสตริง
・ แทนที่ First (String regex, การเปลี่ยนสตริง) ซึ่งโดยทั่วไปเหมือนกับ replaceall ความแตกต่างคือการจับคู่แรกเท่านั้นที่จะถูกแทนที่
ถัดไปมีข้อกำหนดง่าย ๆ ซึ่งคือการแทนที่ A ในสตริงต้นทางด้วย /a รหัสมีดังนี้:
System.out.println ("ABAC". REPLACE ("A", "// A")); ///ab/acsystem.out.println("abac".replaceall("a "," // a ")); //abacsystem.out.println("Abac".RaplaceFirst("a "," // a ")); //abacsystem.out.println("Abac".RaplaceFirst("a "," // a ")); // ABACผลที่ได้คือความประหลาดใจที่ยิ่งใหญ่ หลังจากหลายปีของการแทนที่ฉันก็สับสนเล็กน้อย
สตริงต้นทางคือ "ABAC" จากนั้นเราก็พบว่า "A" แทนที่ด้วย /A เนื่องจาก /เป็นตัวละคร Java Escape หากคุณต้องการแสดง /A คุณต้องเขียน "// a" backslash ตัวแรกจะหลบหนี backslash ที่สองลงในสตริงปกติ
ด้วยนิพจน์การเปลี่ยนสามครั้งผลลัพธ์ของฟังก์ชั่นการแทนที่ครั้งแรกเท่านั้นที่ถูกต้อง ปัญหาคืออะไร?
replaceall และ replactfirst ต้องการให้พารามิเตอร์แรกเป็นนิพจน์ทั่วไป "A" สามารถเข้าใจได้ว่าทั้งสตริง A และนิพจน์ปกติ A ดังนั้นพารามิเตอร์แรกจึงใช้ได้
ปัญหาอยู่ในพารามิเตอร์ที่สอง หากผู้อ่านอ่านความคิดเห็นของฟังก์ชั่น reflaceall อย่างระมัดระวังพวกเขาจะพบคำอธิบายต่อไปนี้:
โปรดทราบว่า backslashes (/) และสัญญาณดอลลาร์ ($) ในสตริงทดแทนอาจทำให้ผลลัพธ์แตกต่างจากถ้ามันได้รับการปฏิบัติเป็นสตริงทดแทนที่แท้จริง; ดู Matcher.replaceall ใช้ java.util.regex.matcher.quotePlacement เพื่อระงับความหมายพิเศษของอักขระเหล่านี้หากต้องการ
เนื่องจากพารามิเตอร์แรกของ replaceall และ replactfirst เป็นปกติเราสามารถทำเทคนิคเล็ก ๆ ในพารามิเตอร์ที่สองเช่นข้อกำหนด: แทนที่ A ในสตริงต้นทางด้วยอักขระทันทีหลังจาก A รหัสดังต่อไปนี้:
System.out.println ("ABAC" .replaceall ("A (// w)", "$ 1 $ 1")); //bbccsystem.out.println("abac".replacefirst("a(/w) "," $ 1 $ 1 ")); // bbacสมมติว่าความหมายของความสม่ำเสมอสามารถเข้าใจได้โดยผู้อ่านจะเห็นได้ว่าในพารามิเตอร์ที่สองสามารถใช้สัญลักษณ์ $ เพื่อรับเนื้อหาของกลุ่มได้ ในตัวอย่างนี้ใช้ $ 1 เพื่อรับเนื้อหาของกลุ่มแรกนั่นคืออักขระทันทีหลังจาก
ดังนั้นสัญลักษณ์ $ มีความหมายพิเศษในพารามิเตอร์ที่สองและการเขียนแบบสุ่มจะทำให้เกิดข้อผิดพลาด:
System.out.println ("ABAC" .replaceall ("A (// w)", "$")); // ข้อยกเว้นในเธรด "Main" Java.lang.StringIndExOutOfBoundSexception: ดัชนีสตริงออกจากช่วง: 1ถ้าฉันแค่ต้องการแทนที่ด้วย $? สิ่งนี้ต้องใช้ตัวละครที่หลบหนี:
System.out.println ("ABAC" .replaceall ("A", "// $")); // $ b $ cเมื่อมาถึงจุดนี้ผู้อ่านอาจตระหนักว่า backslash มีความหมายพิเศษ (หลบหนี) ในพารามิเตอร์ที่สองดังนั้นหากเราต้องการแสดง backslash เราต้องหลบหนีอีกครั้ง:
System.out.println ("ABAC" .replaceall ("A", "//// A")); ///ab/acsystem.out.println("abac".replacefirst("a "," //////////////////////////6-/0งงในซึ่ง)); /// ABACเพื่อทำความเข้าใจสั้น ๆ backslash ด้านหน้าใน "//// a" หนีกลับ backslash หลังจากนั้นเพื่อให้ backslash หลังจากนั้นเป็นสายปกติ ด้วยวิธีนี้สตริงที่เห็นในหน่วยความจำ Java คือ "// a" เมื่อการประมวลผลฟังก์ชั่น replaceall ใช้ backslash ด้านหน้าเพื่อหลบหนี backslash หลังจากนั้นเพื่อแสดงว่า backslash หลังจากนั้นเป็นสตริงธรรมดาไม่ได้ใช้เพื่อหลบหนี $ และสตริงสุดท้ายในหน่วยความจำคือ " /a" เพื่อให้สามารถแทนที่ด้วย /a ได้สำเร็จ
สรุป
ปัญหาการหลบหนีนั้นยุ่งเหยิง ผ่านบทความนี้ผู้เขียนหวังว่าผู้อ่านจะสามารถตื่นขึ้นมาได้เมื่อใช้ฟังก์ชั่นเหล่านี้ในอนาคตโปรดระวังตัวละครพิเศษในพารามิเตอร์และหลีกเลี่ยงการเขียนระเบิดเวลา ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาและการทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร