Rust में रहस्यमय r#""# के पीछे क्या छिपा है? कोड के साथ पूर्ण व्याख्या
\n\nक्या आपने कभी Rust कोड में r#"..."# जैसी अजीब लिखावट देखी है और सोचा है: "यह कौन सा जादुई ऑपरेटर है? क्या यह चुनिंदा लोगों के लिए कोई गुप्त सिंटैक्स है?" — आप अकेले नहीं हैं। हजारों डेवलपर्स ने Stack Overflow पर यह सवाल पूछा है, और आज हम हमेशा के लिए समझ लेंगे कि यह क्या है, इसकी आवश्यकता क्यों है, और Rust में रॉ स्ट्रिंग लिटरल (raw string literals) का उपयोग कैसे करें।
इस लेख में हम केवल एक सूखी परिभाषा नहीं देंगे। हम समस्या से समाधान तक का सफर तय करेंगे, वास्तविक कोड लिखेंगे, देखेंगे कि कैसे r#""# सिरदर्द से बचाता है, और जानेंगे कि यह सिंटैक्स और कहाँ उपयोग होता है। चलिए शुरू करते हैं!
समस्या: जब सामान्य स्ट्रिंग्स कोड को तोड़ देती हैं
\n\nकल्पना करें कि आप एक JSON पार्सर या रेगुलर एक्सप्रेशन लिख रहे हैं। स्ट्रिंग के अंदर आपको कोट्स और बैकस्लैश का उपयोग करना होगा। सामान्य Rust कोड में यह एक बुरे सपने जैसा दिखता है:
\n\nlet json_string = "{\\"name\\": \\"Rust\\", \\"year\\": 2015}";\nlet regex = "\\\\d{2}-\\\\d{2}-\\\\d{4}"; // दिनांक प्रारूप DD-MM-YYYY\n\nइसे देखिए? हर बार जब आपको स्ट्रिंग के अंदर कोट की आवश्यकता होती है, आप उसके सामने बैकस्लैश लगाते हैं (\\"). और अगर आपको स्वयं बैकस्लैश चाहिए — तो आप \\\\ लिखते हैं। कोड जल्दी ही स्लैश की "सीढ़ी" में बदल जाता है जिसे पढ़ना और डीबग करना मुश्किल होता है।
लेकिन यह तो शुरुआत है। क्या होगा अगर आपको स्ट्रिंग में टैबुलेशन कैरेक्टर डालना है? तब आप \\t लिखते हैं। और अगर आपको शाब्दिक रूप से \\t टेक्स्ट चाहिए? तो आपको एस्केप करना होगा: \\\\t. दूसरी पंक्ति तक आँखों में दर्द होने लगता है।
समाधान: रॉ स्ट्रिंग्स — r#""#
\n\nRust एक सुंदर समाधान प्रदान करता है — रॉ स्ट्रिंग लिटरल। इन्हें उपसर्ग r से दर्शाया जाता है और # में बांधा जाता है:
// रॉ स्ट्रिंग: अंदर की हर चीज़ शाब्दिक टेक्स्ट मानी जाती है\nlet raw_json = r#"{"name": "Rust", "year": 2015}"#;\nlet raw_regex = r#"\\d{2}-\\d{2}-\\d{4}"#;\n\nअंतर महसूस कर रहे हैं? कोई एस्केपिंग नहीं! अंदर के कोट्स सिर्फ कोट्स हैं। बैकस्लैश सिर्फ स्लैश हैं। Rust कंपाइलर r#" और "# के बीच की सामग्री को शुद्ध टेक्स्ट के रूप में मानता है, एस्केप सीक्वेंस की व्याख्या करने का प्रयास नहीं करता।
यह विशेष रूप से उपयोगी है जब आप इसके साथ काम करते हैं:
\n- \n
- रेगुलर एक्सप्रेशन — वे स्लैश और विशेष वर्णों से भरे होते हैं। \n
- JSON, XML, HTML — ढेर सारे कोट्स वाली स्ट्रिंग्स। \n
- SQL क्वेरीज़ — विशेष रूप से नेस्टेड कोट्स के साथ। \n
- Windows में फ़ाइल पथ —
C:\\Users\\NameबनामC:\\\\Users\\\\Name। \n - कोई भी डेटा जहाँ बैकस्लैश को ज्यों का त्यों रहना चाहिए। \n
यह अंदरूनी रूप से कैसे काम करता है?
\n\nजब Rust r#"..."# देखता है, तो वह बस शुरुआती r#" और अंतिम "# के बीच की हर चीज़ को बिना किसी प्रसंस्करण के स्ट्रिंग में कॉपी कर लेता है। कोई \\n न्यूलाइन में नहीं बदलता, कोई \\t टैब नहीं बनता। यह टेक्स्ट का एक शाब्दिक टुकड़ा है।
लेकिन एक बारीक बात है: अगर स्ट्रिंग के अंदर ही "# अनुक्रम आ जाए तो क्या करें? उदाहरण के लिए, आप #"hello"# टेक्स्ट डालना चाहते हैं। यदि आप r#"#"hello"#"# लिखते हैं, तो कंपाइलर भ्रमित हो जाएगा — लिटरल कहाँ समाप्त होता है?
इसके लिए Rust में एकाधिक हैश का प्रावधान है। आप r##"..."##, r###"..."### इत्यादि का उपयोग कर सकते हैं। दोनों तरफ # की संख्या समान होनी चाहिए:
// स्ट्रिंग में "# है — डबल हैश का उपयोग करें\nlet tricky = r##"स्ट्रिंग जिसमें "# है"##;\nprintln!("{}", tricky); // आउटपुट: स्ट्रिंग जिसमें "# है\n\n// और अगर अंदर "## है? तब ट्रिपल हैश:\nlet very_tricky = r###"टेक्स्ट जिसमें "## है"###;