TLDR: ใช้theString = theString.replace("\\", "\\\\");
แทน
ปัญหา
replaceAll(target, replacement)
ใช้การแสดงออกปกติ (regex) ไวยากรณ์สำหรับและบางส่วน target
replacement
ปัญหาคือ\
อักขระพิเศษใน regex (สามารถใช้\d
เพื่อแทนตัวเลข) และใน String literal (สามารถใช้"\n"
เพื่อแสดงตัวคั่นบรรทัดหรือ\"
เพื่อหลีกเลี่ยงสัญลักษณ์เครื่องหมายคำพูดคู่ซึ่งโดยปกติจะแสดงจุดสิ้นสุดของสตริงตามตัวอักษร)
ในทั้งสองกรณีนี้ในการสร้าง\
สัญลักษณ์เราสามารถหลีกเลี่ยงมันได้ (ทำให้เป็นตัวอักษรแทนอักขระพิเศษ) โดยวางเพิ่มเติมไว้ข้าง\
หน้า (เช่นเราหลบหนี"
ในตัวอักษรสตริงผ่าน\"
)
ดังนั้นในการtarget
regex ที่แสดง\
สัญลักษณ์จะต้องมีค้างไว้\\
และสตริงตามตัวอักษรที่แสดงข้อความดังกล่าวจะต้องมีลักษณะ"\\\\"
ดังนี้
เราจึงหนี\
สองครั้ง:
- ครั้งเดียวใน regex
\\
- หนึ่งครั้งใน String literal
"\\\\"
(แต่ละตัว\
จะแสดงเป็น"\\"
)
ในกรณีreplacement
\
พิเศษยังมี ช่วยให้เราสามารถหลีกเลี่ยงอักขระพิเศษอื่น ๆ$
ซึ่งผ่าน$x
สัญกรณ์ช่วยให้เราใช้ส่วนของข้อมูลที่จับคู่โดย regex และถือครองโดยการจับกลุ่มที่จัดทำดัชนีเนื่องจากx
เหมือน"012".replaceAll("(\\d)", "$1$1")
จะตรงกับแต่ละหลักวางไว้ในการจับกลุ่ม 1 และ$1$1
จะแทนที่ด้วยสองสำเนา (มันจะซ้ำ) "001122"
ที่เกิดขึ้นใน
ดังนั้นอีกครั้งเพื่อให้replacement
เป็นตัวแทน\
ตามตัวอักษรเราจำเป็นต้องหลีกเลี่ยงมันด้วยเพิ่มเติม\
ซึ่งหมายความว่า:
- การแทนที่ต้องมีอักขระเครื่องหมายทับขวาสองตัว
\\
- และสตริงลิเทอรัลซึ่งแสดงถึง
\\
ลักษณะ"\\\\"
แต่เนื่องจากเราต้องการreplacement
ถือแบ็กสแลชสองตัวเราจึงจำเป็นต้องใช้"\\\\\\\\"
(แต่ละตัว\
แสดงด้วยหนึ่ง"\\\\"
)
ดังนั้นเวอร์ชันที่มีreplaceAll
ลักษณะเช่นนี้
replaceAll("\\\\", "\\\\\\\\");
วิธีที่ง่ายกว่า
เพื่อให้ชีวิตง่ายขึ้น Java มีเครื่องมือในการหลีกเลี่ยงข้อความเข้าtarget
และreplacement
ส่วนต่างๆโดยอัตโนมัติ ตอนนี้เราสามารถมุ่งเน้นเฉพาะสตริงและลืมเกี่ยวกับไวยากรณ์ regex:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
ซึ่งในกรณีของเราอาจมีลักษณะดังนี้
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
ดียิ่งขึ้น
หากเราไม่ต้องการการสนับสนุนไวยากรณ์ regex จริงๆอย่าให้เกี่ยวข้องreplaceAll
เลย replace
แทนที่จะช่วยให้การใช้งาน ทั้งสองวิธีจะแทนที่s ทั้งหมด target
แต่replace
ไม่เกี่ยวข้องกับไวยากรณ์ regex คุณก็เขียนได้
theString = theString.replace("\\", "\\\\");