डबल बैकस्लैश के साथ String.replaceAll एकल बैकस्लैश


122

मैं प्रयोग String \something\में बदलने की कोशिश कर रहा हूं , लेकिन मुझे हर तरह की त्रुटियां होती रहती हैं। मैंने सोचा कि यह समाधान था:String \\something\\replaceAll

theString.replaceAll("\\", "\\\\");

लेकिन यह निम्न अपवाद देता है:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1

जवाबों:


204

String#replaceAll()एक नियमित अभिव्यक्ति के रूप में तर्क की व्याख्या करता है । \में एक एस्केप वर्ण है, दोनों String और regex। Regex के लिए आपको इसे डबल-एस्केप करना होगा:

string.replaceAll("\\\\", "\\\\\\\\");

लेकिन इसके लिए आपको आवश्यक रूप से regex की आवश्यकता नहीं है, सिर्फ इसलिए कि आप एक सटीक चरित्र-दर-स्थान प्रतिस्थापन चाहते हैं और आपको यहां पैटर्न की आवश्यकता नहीं है। तो String#replace()पर्याप्त होना चाहिए:

string.replace("\\", "\\\\");

अपडेट : टिप्पणियों के अनुसार, आप स्ट्रिंग को जावास्क्रिप्ट संदर्भ में उपयोग करना चाहते हैं। StringEscapeUtils#escapeEcmaScript()अधिक वर्णों को कवर करने के बजाय आप शायद बेहतर उपयोग करेंगे ।


वास्तव में, इसका उपयोग जावास्क्रिप्ट एएसटी में किया जाता है जिसे वापस स्रोत में परिवर्तित किया जाना चाहिए। आपका समाधान काम करता है। धन्यवाद!
फ्रैंक ग्रोएनेल्ड

2
यदि आप किसी String#replaceAll()भी तरह से उपयोग करना चाहते हैं , तो आप मिलानकर्ता के साथ प्रतिस्थापन स्ट्रिंग को उद्धृत कर सकते हैं # quotReplacement () :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
phse

Matcher.quoteReplacement (...) एक अच्छा तरीका है! कृपया Pshemo का उत्तर देखें!
हार्टमुट पी।

14

इस तरह की परेशानी से बचने के लिए, आप replace(जो एक सामान्य स्ट्रिंग लेता है) का उपयोग कर सकते हैं (जो replaceAllएक नियमित अभिव्यक्ति लेता है)। आपको अभी भी बैकस्लैश से बचने की आवश्यकता होगी, लेकिन नियमित अभिव्यक्ति के साथ आवश्यक जंगली तरीकों से नहीं।


10

TLDR: theString = theString.replace("\\", "\\\\");इसके बजाय का उपयोग करें ।


संकट

replaceAll(target, replacement)के लिए targetऔर आंशिक रूप से के लिए नियमित अभिव्यक्ति (रेगेक्स) वाक्यविन्यास का उपयोग करता है replacement

समस्या यह है कि \रेगेक्स में विशेष चरित्र है (इसका उपयोग \dअंक का प्रतिनिधित्व करने के लिए किया जा सकता है ) और स्ट्रिंग शाब्दिक में (इसका उपयोग "\n"लाइन विभाजक का प्रतिनिधित्व \"करने के लिए या दोहरे उद्धरण चिन्ह से बचने के लिए किया जा सकता है जो आमतौर पर स्ट्रिंग शाब्दिक के अंत का प्रतिनिधित्व करता है)।

\प्रतीक बनाने के लिए इन दोनों मामलों में हम इससे पहले अतिरिक्त रखकर (जैसे हम स्ट्रिंग साहित्यिकों में बचते हैं ) से बच सकते हैं (विशेष चरित्र के बजाय इसे शाब्दिक बना सकते हैं )।\"\"

तो प्रतीक का targetप्रतिनिधित्व करने के लिए regex \को पकड़ना होगा \\, और ऐसे पाठ का प्रतिनिधित्व करने वाले स्ट्रिंग शाब्दिक को देखने की आवश्यकता होगी "\\\\"

इसलिए हम \दो बार भाग निकले :

  • एक बार regex में \\
  • एक बार स्ट्रिंग शाब्दिक में "\\\\"(प्रत्येक \का प्रतिनिधित्व किया जाता है "\\")।

के मामले में replacement \भी खास है। यह हमें अन्य विशेष चरित्र से बचने की अनुमति देता है, $जो $xसंकेतन के माध्यम से , हमें regex द्वारा मिलान किए गए डेटा के हिस्से का उपयोग करने की अनुमति देता है और समूह द्वारा अनुक्रमित कैप्चरिंग के रूप में आयोजित किया जाता है x, जैसे "012".replaceAll("(\\d)", "$1$1")कि प्रत्येक अंक से मेल खाएगा, इसे कैप्चरिंग ग्रुप 1 में रखें और $1$1इसे अपनी दो प्रतियों के साथ बदल देगा। (यह इसे डुप्लिकेट करेगा) जिसके परिणामस्वरूप "001122"

तो फिर, शाब्दिक replacementप्रतिनिधित्व \करने के लिए हमें इसे अतिरिक्त के साथ भागने की आवश्यकता है \जिसका अर्थ है:

  • प्रतिस्थापन में दो बैकस्लैश वर्ण होने चाहिए \\
  • और स्ट्रिंग शाब्दिक जो प्रतिनिधित्व करता \\है जैसा दिखता है"\\\\"

लेकिन जब से हम दो बैकस्लैश replacementको पकड़ना चाहते हैं, तो हमें आवश्यकता होगी (प्रत्येक का प्रतिनिधित्व एक )।"\\\\\\\\"\"\\\\"

तो के साथ संस्करण की replaceAllतरह लग सकता है

replaceAll("\\\\", "\\\\\\\\");

आसान तरीका है

जीवन को आसान बनाने के लिए जावा पाठ targetऔर replacementभागों में स्वचालित रूप से भागने के लिए उपकरण प्रदान करता है । तो अब हम केवल स्ट्रिंग्स पर ध्यान केंद्रित कर सकते हैं, और रेगेक्स सिंटैक्स के बारे में भूल सकते हैं:

replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))

जो हमारे मामले में दिख सकता है

replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))

और भी बेहतर

अगर हमें वास्तव में रेगेक्स सिंटैक्स समर्थन की आवश्यकता नहीं है, तो यह बिल्कुल भी शामिल नहीं होने देता है replaceAll। इसके बजाय उपयोग करने देता है replace। दोनों विधियां सभी target s को बदल देंगी , लेकिन replaceरेगेक्स सिंटैक्स को शामिल नहीं करती हैं। तो आप बस लिख सकते हैं

theString = theString.replace("\\", "\\\\");

7

आपको पहले तर्क में (बच गए) बैकस्लैश से बचना होगा क्योंकि यह एक नियमित अभिव्यक्ति है। रिप्लेसमेंट (दूसरा तर्क - देखें माचिस # रिप्लेसमेंट ( स्ट्रिंग) ) इसमें बैकस्लैश का विशेष अर्थ भी है, इसलिए आपको इन्हें बदलना होगा:

theString.replaceAll("\\\\", "\\\\\\\\");

3

हां ... जब तक रेगेक्स कंपाइलर आपके द्वारा दिए गए पैटर्न को देखता है, तब तक वह केवल एक ही बैकस्लैश देखता है (चूंकि जावा के लेक्सर ने डबल बैकवॉक को एक सिंगल में बदल दिया है)। आप प्रतिस्थापित करने की आवश्यकता "\\\\"के साथ "\\\\", यह विश्वास है या नहीं! जावा को वास्तव में एक अच्छे कच्चे स्ट्रिंग सिंटैक्स की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.