title = "Blue = Green" जैसे असाइनमेंट निकालने के लिए, कुंजी और पूरे उद्धृत मान का एक साथ मिलान करें। Mac के लिए यह मार्गदर्शिका Safari में JavaScript का उपयोग करके आंतरिक समान चिह्नों, उद्धरण चिह्नों और बैकस्लैश को जस का तस रखती है और गलत फ़ॉर्मैट वाली पंक्तियों की सूचना देती है।
समान चिह्नों पर विभाजित करने से मान क्यों खो जाता है?
इस कृत्रिम असाइनमेंट पर विचार करें:
title = "Blue = Green"
इच्छित कुंजी title है; मूल उद्धरण चिह्नों समेत मान "Blue = Green" है। केवल पहला समान चिह्न फ़ील्डों को अलग करता है। दूसरा उद्धृत पाठ का हिस्सा है।
JavaScript का split("=") उद्धरण चिह्नों का अर्थ समझे बिना हर बार मिलने पर विभाजित करता है। split("=", 2) की तरह सीमा जोड़ने से प्राप्त ऐरे छोटा हो जाता है; इससे पहले विभाजक के बाद का पूरा हिस्सा सुरक्षित नहीं रहता। यह मानक में String.prototype.split की परिभाषा के अनुरूप है।
सही तरीका इनपुट के व्याकरण पर निर्भर करता है। पाठ बदलने से पहले इस निर्णय-सहायिका का उपयोग करें:
| इनपुट की स्थिति | उपयुक्त तरीका |
|---|---|
| हर पंक्ति में एक असाइनमेंट; केवल अलग करना ज़रूरी | पहला समान चिह्न खोजें और उसके बाद का पूरा हिस्सा रखें। |
| हर पंक्ति में एक असाइनमेंट; उद्धरण चिह्नों और कुंजी के सिंटैक्स की भी जाँच करनी है | नीचे दिए गए अनुसार, पूरी पंक्ति का मिलान किसी परिभाषित असाइनमेंट पैटर्न से करें। |
| हर पंक्ति में कई असाइनमेंट या कई पंक्तियों में फैले मान | ऐसे अतिरिक्त नियमों के लिए बनाए गए पार्सर का उपयोग करें। |
इस काम में, पूरी पंक्ति का सत्यापन एक उपयोगी अतिरिक्त जाँच देता है: बेमेल उद्धरण चिह्न या अप्रत्याशित पीछे का पाठ अधूरे निष्कर्षण के बजाय त्रुटि पैदा करता है।
यह उदाहरण असाइनमेंट के किस व्याकरण को सुरक्षित रखता है?
नीचे दिया गया प्रोग्राम जानबूझकर एक छोटा पाठ फ़ॉर्मैट लागू करता है। ये इसके निर्धारित नियम हैं, यह दावा नहीं कि यह हर JavaScript असाइनमेंट को पार्स करता है:
- हर गैर-रिक्त पंक्ति में एक असाइनमेंट होता है।
- कुंजियाँ ASCII अक्षर या अंडरस्कोर से शुरू होती हैं, जिसके बाद ASCII अक्षर, अंक या अंडरस्कोर आते हैं।
- मानों में मेल खाते सीधे एकल या दोहरे उद्धरण चिह्न होते हैं। खाली उद्धृत मान मान्य हैं।
- मान के भीतर, बैकस्लैश के बाद अगला अक्षर आता है, सिवाय कैरिज रिटर्न या नई पंक्ति के। दोनों अक्षर अपरिवर्तित रहते हैं।
- कुंजी, विभाजक और मान के आसपास रिक्त स्थान और टैब हो सकते हैं। उद्धरण चिह्नों के भीतर के रिक्त स्थान और टैब मान का हिस्सा रहते हैं।
- भौतिक पंक्ति-अंत LF, CRLF या CR हो सकते हैं। उद्धृत मान इन पंक्ति-अंतों के पार नहीं जा सकते।
- टिप्पणियाँ, अर्धविराम और बिना उद्धरण वाले मान इस व्याकरण से बाहर हैं।
उदाहरण के लिए, caption='Small = calm' मान्य है। note="Use \"a=b\" here" भी मान्य है: एस्केप किए गए दोहरे उद्धरण चिह्न मान का हिस्सा हैं। इसके विपरीत, caption='Small = calm" में सीमांकन चिह्न मेल नहीं खाते और इसे ठीक करना होगा।
आउटपुट हर मान को rawValue के रूप में रखता है, जिसमें उसके चारों ओर के उद्धरण चिह्न भी शामिल हैं। निष्कर्षण एस्केप सीक्वेंस को डीकोड नहीं करता: \n के दोनों अक्षर दो अक्षर ही रहते हैं। इससे परिणाम असाइनमेंट के लिखित रूप को बदले बिना उसका क्रम बदलने के लिए उपयुक्त रहता है।
दोहराई गई कुंजियाँ भी अपने मूल क्रम में अलग-अलग प्रविष्टियों के रूप में रहती हैं। इससे वही कुंजी दोबारा आने पर पहले का मान चुपचाप बदलने से बचता है।
Mac पर Safari में यह रूपांतरण कैसे चलाएँ?
Safari का Web Inspector JavaScript चलाने की जगह देता है। इसे Safari → Settings… → Advanced → Show features for web developers के ज़रिए सक्षम करें। फिर Develop → Show Web Inspector चुनें या Option-Command-I दबाएँ। इन चरणों का दस्तावेज़ WebKit की Web Inspector सक्षम करना में दिया गया है।
Console टैब चुनें और नीचे दिए गए पूरे प्रोग्राम को उसके इनपुट प्रॉम्प्ट में डालें। WebKit इस प्रॉम्प्ट को अपने Web Inspector Interface संदर्भ में JavaScript चलाने के लिए इनपुट फ़ील्ड के रूप में दर्ज करता है। यह उदाहरण केवल प्रोग्राम के भीतर लिखी गई स्ट्रिंग पर काम करता है।
नमूने में String.raw का उपयोग है, ताकि JavaScript स्ट्रिंग बनाते समय बैकस्लैश जस के तस रहें। नमूने को संपादित करते समय याद रखें कि बैकटिक और ${...} का टेम्पलेट लिटरल में विशेष अर्थ है; इस इनपुट में इनमें से कोई नहीं है। इन अक्षरों को जोड़ने से पहले JavaScript String.raw() दस्तावेज़ देखें।
(() => {
const source = String.raw`title = "Blue = Green"
caption='Small = calm'
note = "Use \"a=b\" here"
marker = "$1 = $$"
empty = ""`;
const assignment = /^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*=[ \t]*("(?:\\[^\r\n]|[^"\\\r\n])*"|'(?:\\[^\r\n]|[^'\\\r\n])*')[ \t]*$/;
function extractAssignments(text) {
const pairs = [];
const errors = [];
const lines = text.split(/\r\n|\n|\r/);
lines.forEach((line, index) => {
if (/^[ \t]*$/.test(line)) return;
const match = assignment.exec(line);
if (!match || match[0].length !== line.length) {
errors.push(`Line ${index + 1}: expected key = quoted value`);
return;
}
pairs.push({ key: match[1], rawValue: match[2] });
});
if (errors.length) throw new Error(errors.join("\n"));
return pairs;
}
const pairs = extractAssignments(source);
const extracted = pairs
.map(({ key, rawValue }) => `key: ${key}\nvalue: ${rawValue}`)
.join("\n\n");
console.log(extracted);
const normalized = source.split(/\r\n|\n|\r/)
.map(line => line.replace(assignment,
(_whole, key, rawValue) => key + " = " + rawValue))
.join("\n");
console.log("Normalized assignments:\n" + normalized);
})();
यह नमूना डेटा वाला पूरा प्रोग्राम है; इसमें कोई इंपोर्ट या अतिरिक्त पैकेज नहीं हैं। इसके चारों ओर का फ़ंक्शन घोषणाओं को स्थानीय रखता है, ताकि नमूना संपादित करने के बाद पूरा उदाहरण फिर से चलाया जा सके।
पहला कंसोल संदेश फ़ील्डों को अलग करके दिखाता है:
key: title
value: "Blue = Green"
key: caption
value: 'Small = calm'
key: note
value: "Use \"a=b\" here"
key: marker
value: "$1 = $$"
key: empty
value: ""
दूसरा संदेश एकसमान रिक्त स्थान वाले असाइनमेंट देता है:
Normalized assignments:
title = "Blue = Green"
caption = 'Small = calm'
note = "Use \"a=b\" here"
marker = "$1 = $$"
empty = ""
डेस्कटॉप पर काम के अनुकूल पाठ खंड चुनकर कॉपी करें। प्रोग्राम console.log के ज़रिए परिणाम दिखाता है, जिसका दस्तावेज़ WebKit के Console Object API में है। यह फ़ाइल नहीं लिखता।
पैटर्न उद्धृत समान चिह्नों को जस का तस कैसे रखता है?
इस पैटर्न में दो कैप्चरिंग समूह हैं: एक कुंजी के लिए और दूसरा पूरे उद्धृत मान के लिए। इसके भीतर के (?:...) समूह बिना अतिरिक्त कैप्चर किए फ़ील्ड बनाए विकल्पों को व्यवस्थित करते हैं। कैप्चरिंग और नॉन-कैप्चरिंग समूहों का यह उपयोग JavaScript समूह दस्तावेज़ के अनुरूप है।
कुंजी का मिलान करने के बाद, पैटर्न असाइनमेंट विभाजक को एक बार पढ़ता है। फिर यह दोहरे उद्धरण वाले या एकल उद्धरण वाले विकल्प में से एक चुनता है। दोनों में सामान्य अक्षर—समान चिह्नों समेत—या बैकस्लैश के बाद आने वाला अक्षर स्वीकार्य है। बिना एस्केप वाला मेल खाता उद्धरण चिह्न उस विकल्प को बंद करता है।
यह संरचना एस्केप किए गए उद्धरण चिह्नों को मान का अंत समझने से बचाती है। यह जोड़े में आए बैकस्लैश को भी संभालती है: एक जोड़ा साथ पढ़े जाने के बाद, अगला बिना एस्केप वाला उद्धरण चिह्न स्ट्रिंग को बंद कर सकता है। खाली मान भी काम करते हैं, क्योंकि उद्धृत सामग्री शून्य बार दोहराई जा सकती है।
प्रोग्राम कैप्चर को match[1] और match[2] के ज़रिए पढ़ता है। असफल exec() कॉल null लौटाती है, जैसा कि ECMAScript के RegExp.prototype.exec में निर्दिष्ट है। अतिरिक्त लंबाई तुलना यह सुनिश्चित करती है कि मिलान पूरी भौतिक पंक्ति को समेटे।
केवल रिक्त स्थान और टैब को आसपास का फ़ॉर्मैटिंग माना जाता है। प्रोग्राम मान के अंदर की सामग्री को कभी ट्रिम नहीं करता। इसलिए label = " Blue = Green " उद्धृत सामग्री के दोनों सिरों पर मौजूद रिक्त स्थान बनाए रखता है।
फ़ॉर्मैट दोबारा देते समय रिप्लेसमेंट फ़ंक्शन का उपयोग क्यों करें?
सामान्यीकरण चरण कैप्चर की गई कुंजी, एक मानकीकृत विभाजक और कैप्चर किया गया मान लौटाता है। इसके रिप्लेसमेंट कॉलबैक को पहले पूरा मिलान और फिर दोनों कैप्चर मिलते हैं। JavaScript इस तर्क क्रम को String.prototype.replace() में दर्ज करता है।
कॉलबैक से लौटाया गया पाठ अक्षरशः डाला जाता है; $1 या $$ जैसे रिप्लेसमेंट टोकन की व्याख्या नहीं की जाती। इससे नमूने का मान "$1 = $$" जस का तस रहता है। यही दस्तावेज़ रिप्लेसमेंट स्ट्रिंग और रिप्लेसमेंट फ़ंक्शन के बीच का यह अंतर भी समझाता है।
"$1 = $2" जैसा स्थिर रिप्लेसमेंट टेम्पलेट भी इस खास पैटर्न के लिए काम करेगा: कैप्चर की गई सामग्री बिना किसी दूसरे सब्स्टिट्यूशन चरण के डाली जाती है। रिप्लेसमेंट पाठ को गतिशील रूप से जोड़ते समय कॉलबैक खास तौर पर उपयोगी होता है, क्योंकि इससे लौटाया गया मान रिप्लेसमेंट टेम्पलेट सिंटैक्स से अलग रहता है।
सामान्यीकरण जानबूझकर आसपास के रिक्त स्थान बदलता है और भौतिक पंक्ति-अंतों को LF में बदलता है। यह खाली पंक्तियाँ और उद्धृत मान का सटीक पाठ सुरक्षित रखता है। अगर काम में मूल रिक्त स्थान और पंक्ति-अंत आवश्यक हैं, तो निरीक्षण के लिए निकाले गए जोड़ों का उपयोग करें और मूल source को अपरिवर्तित रखें।
परिणाम इस्तेमाल करने से पहले क्या जाँचें?
निष्कर्षण फ़ंक्शन पंक्ति संख्या सहित त्रुटियाँ इकट्ठा करता है और दोनों में से कोई भी परिणाम दिखाने से पहले त्रुटि उठाता है। केवल रिक्त स्थान या टैब वाली खाली पंक्तियों को स्पष्ट रूप से अनदेखा किया जाता है। इसलिए गलत फ़ॉर्मैट वाली गैर-रिक्त पंक्ति सफल दिखने वाले अधूरे परिणाम में छिप नहीं सकती।
अप्रत्याशित इनपुट की जाँच के लिए इन कृत्रिम उदाहरणों का उपयोग करें:
| असाइनमेंट पाठ | अपेक्षित परिणाम |
|---|---|
x="a=b=c" |
पूरा उद्धृत मान सुरक्षित रखें। |
x='' |
खाली एकल उद्धरण वाला मान स्वीकार करें। |
x=" a=b " |
उद्धरण चिह्नों के भीतर के रिक्त स्थान सुरक्षित रखें। |
x="a\"=b" |
एस्केप किया गया उद्धरण चिह्न और समान चिह्न सुरक्षित रखें। |
x="a=b |
बंद करने वाला उद्धरण चिह्न न होने की सूचना दें। |
x="a" extra |
पीछे के पाठ की सूचना दें। |
x="a" y="b" |
एक पंक्ति में कई असाइनमेंट अस्वीकार करें। |
x=a=b |
इस व्याकरण के तहत बिना उद्धरण वाले मान को अस्वीकार करें। |
निष्कर्षण और सामान्यीकरण लॉजिक को दिखाए गए नमूने के साथ Node.js 20.19.2 में चलाया गया। पंद्रह अतिरिक्त नियतात्मक जाँचों में उद्धृत समान चिह्न, खाली मान, एस्केप किए गए उद्धरण चिह्न, जोड़े वाले बैकस्लैश, लिटरल डॉलर टोकन, गलत फ़ॉर्मैट वाली पंक्तियाँ, दोहराई गई कुंजियाँ और खाली पंक्तियों का प्रबंधन शामिल था। इससे लिखे गए रूपांतरण लॉजिक की पुष्टि होती है; यह दावा नहीं कि Safari इंटरफ़ेस का परीक्षण किया गया था।
अगर कोई पंक्ति विफल हो, तो पहले उसके सीमांकन चिह्न जाँचें, फिर अंत में बिना जोड़े वाला बैकस्लैश, पीछे का पाठ या असमर्थित कुंजी देखें। जब काम में अधिक सिंटैक्स चाहिए, तो व्याकरण को सोच-समझकर बदलें। बताए गए हर पंक्ति में एक असाइनमेंट वाले फ़ॉर्मैट के लिए, परिणाम दोबारा उपयोग किए जा सकने वाले फ़ील्डों का जोड़ा है, जिसका उद्धृत मान भीतर के हर समान चिह्न को सुरक्षित रखता है।
स्रोत
- Web Inspector सक्षम करना — WebKit।
- Web Inspector Interface — WebKit।
- Console Object API — WebKit।
- ECMAScript® 2027 भाषा विनिर्देश — पाठ संसाधन — Ecma International / TC39, निरंतर अद्यतन मसौदा।
- String.raw() — MDN Web Docs।
- समूह और बैकरेफ़रेंस — MDN Web Docs।
- String.prototype.replace() — MDN Web Docs।