मैंने हाल ही में एक लेख प्रकाशित किया जिसमें मैंने कुछ यूनिकोड वर्णों के साथ रूबी की अधिकांश स्ट्रिंग विधियों का परीक्षण किया ताकि यह देखने के लिए कि वे अप्रत्याशित रूप से व्यवहार करेंगे या नहीं। उनमें से कई ने किया।
एक आलोचना जो कुछ लोगों ने लेख की थी वह यह थी कि मैं परीक्षण के लिए असामान्य तारों का उपयोग कर रहा था। सच कहूँ तो, मैं यूनिकोड सामान्यीकरण पर थोड़ा फजी था। मुझे संदेह है कि कई रूबी वादक हैं।
सामान्यीकरण का उपयोग करके, आप कई यूनिकोड स्ट्रिंग्स ले सकते हैं जो मेरे परीक्षणों में अप्रत्याशित रूप से व्यवहार करते हैं और उन्हें स्ट्रिंग्स में परिवर्तित करते हैं जो रूबी की स्ट्रिंग विधियों के साथ अच्छी तरह से खेलते हैं। हालांकि:
- रूपांतरण हमेशा सही नहीं होता है। कुछ यूनिकोड अनुक्रम हमेशा रूबी की स्ट्रिंग विधियों को गलत व्यवहार करने का कारण बनते हैं।
- यह कुछ ऐसा है जो आपको मैन्युअल रूप से करना है। डिफ़ॉल्ट रूप से न तो रूबी, न ही रेल और न ही डीबी स्वचालित रूप से सामान्य हो जाती है।
यह लेख रूबी में यूनिकोड सामान्यीकरण का एक संक्षिप्त परिचय होगा। उम्मीद है कि यह आपको अपने स्वयं के अन्वेषणों के लिए एक महत्वपूर्ण बिंदु प्रदान करेगा।
आइए एक स्ट्रिंग को सामान्य करें
<ब्लॉकक्वॉट>
String#unicode_normalize
रूबी 2.2 में विधि पेश की गई थी। रूबी में लिखा जा रहा है, यह utf8_proc और यूनिकोड रत्न जैसे सामान्यीकरण पुस्तकालयों जितना तेज़ नहीं है जो सी का लाभ उठाते हैं।
हमें सामान्यीकरण की आवश्यकता का कारण यह है कि यूनिकोड में चरित्र लिखने के एक से अधिक तरीके हैं। पत्र "Å"
कोड बिंदु के रूप में दर्शाया जा सकता है "\u00c5"
या अक्षर "A" और एक उच्चारण की संरचना के रूप में:"A\u030A"
।
सामान्यीकरण एक रूप को दूसरे रूप में परिवर्तित करता है:
"A\u030A".unicode_normalize #=> 'Å' (same as "\u00C5")
बेशक, यूनिकोड को सामान्य करने का केवल एक ही तरीका नहीं है। यह बहुत आसान होगा! सामान्य करने के चार तरीके हैं, जिन्हें "सामान्यीकरण रूप" कहा जाता है। इनका नाम गुप्त समरूपों का उपयोग करके रखा गया है:NFD, NFC, NFKD और NFKC।
String#unicode_normalize
डिफ़ॉल्ट रूप से NFC का उपयोग करता है, लेकिन हम इसे किसी अन्य फ़ॉर्म का उपयोग करने के लिए कह सकते हैं जैसे:
"a\u0300".unicode_normalize(:nfkc) #=> 'à' (same as "\u00E0")
लेकिन इसका वास्तव में क्या मतलब है? चार सामान्यीकरण रूप वास्तव में क्या करते हैं? आइए एक नज़र डालते हैं।
सामान्यीकरण फ़ॉर्म
सामान्यीकरण कार्य दो प्रकार के होते हैं:
- रचना: बहु-कोड-बिंदु वर्णों को एकल कोड बिंदुओं में परिवर्तित करता है। उदाहरण के लिए:
"a\u0300"
हो जाता है"\u00E0"
, ये दोनों ही वर्ण को कूटबद्ध करने के तरीके हैंà
। - अपघटन: रचना के विपरीत। एकल-कोड-बिंदु वर्णों को एकाधिक कोड बिंदुओं में परिवर्तित करता है। उदाहरण के लिए:
"\u00E0"
"a\u0300"
. बन जाता है ।
रचना और अपघटन प्रत्येक दो तरीकों से किया जा सकता है:
- कैननिकल: ग्लिफ़ को संरक्षित करता है। उदाहरण के लिए:
"2⁵"
रहता है"2⁵"
भले ही कुछ सिस्टम सुपरस्क्रिप्ट-पांच वर्ण का समर्थन न करें। - संगतता: ग्लिफ़ को उनके संगतता वर्णों से बदल सकते हैं। उदाहरण के लिए:
"2⁵"
"2 5"
. में बदल दिया जाएगा ।
चार "सामान्यीकरण प्रपत्र" बनाने के लिए दो संचालन और दो विकल्प विभिन्न तरीकों से संयुक्त होते हैं। इनपुट और आउटपुट के विवरण और उदाहरणों के साथ, मैंने उन सभी को नीचे दी गई तालिका में सूचीबद्ध किया है:
नाम | <थ>विवरणइनपुट | आउटपुट | |
---|---|---|---|
एनएफडी | कैननिकल अपघटन | Å "\u00c5" | Å "A\u030A" |
एनएफसी | कैननिकल अपघटन के बाद विहित संरचना | Å "A\u030A" | Å "\u00c5" |
एनएफकेडी | संगतता अपघटन | ẛ̣ "\u1e9b\u0323" | ṩ "\u0073\u0323\u0307" |
एनएफकेसी | संगतता अपघटन के बाद विहित संरचना | ẛ̣ "\u1e9b\u0323" | ṩ "\u1e69" |
यदि आप इस तालिका को कुछ मिनटों के लिए देखते हैं, तो आप यह नोट करना शुरू कर सकते हैं कि समरूपी एक तरह से अर्थपूर्ण हैं:
- "NF" का अर्थ "सामान्यीकरण प्रपत्र" है।
- "D" का अर्थ "अपघटन" है
- "C" का अर्थ "रचना" है
- "K" का अर्थ "संगतता" है :)
अधिक उदाहरणों और अधिक विस्तृत तकनीकी स्पष्टीकरण के लिए, यूनिकोड मानक अनुलग्नक #15 देखें।
सामान्यीकरण फ़ॉर्म चुनना
आपके द्वारा उपयोग किया जाने वाला सामान्यीकरण प्रपत्र कार्य पर निर्भर करता है। नीचे दी गई मेरी सिफारिशें यूनिकोड सामान्यीकरण अक्सर पूछे जाने वाले प्रश्नों पर आधारित हैं।
स्ट्रिंग संगतता के लिए NFC का उपयोग करें
यदि आपका लक्ष्य रूबी की स्ट्रिंग विधियों को अधिकांश यूनिकोड के साथ अच्छी तरह से खेलना है, तो संभवतः आप एनएफसी का उपयोग करना चाहेंगे। String#unicode_normalize
. के लिए यह डिफ़ॉल्ट होने का एक कारण है ।
- जहां संभव हो, यह बहु-कोड-बिंदु वर्णों को एकल कोड बिंदुओं में बनाता है। बहु-कोड-बिंदु वर्ण स्ट्रिंग विधियों के साथ अधिकांश समस्याओं का स्रोत हैं।
- यह ग्लिफ़ को नहीं बदलता है, इसलिए आपके अंतिम-उपयोगकर्ताओं को उनके द्वारा इनपुट किए गए टेक्स्ट में कोई बदलाव दिखाई नहीं देगा।
उस ने कहा, सभी बहु-कोड-बिंदु वर्णों को एकल कोड बिंदु में नहीं बनाया जा सकता है। उन मामलों में रूबी की स्ट्रिंग विधियां खराब व्यवहार करेंगी:
s = "\u01B5\u0327\u0308" # => "Ƶ̧̈", an un-composable character
s.unicode_normalize(:nfc).size # => 3, even though there's only one character
सुरक्षा और DB संगतता के लिए NFKC का उपयोग करें
यदि आप सुरक्षा से संबंधित टेक्स्ट जैसे उपयोगकर्ता नाम के साथ काम कर रहे हैं, या मुख्य रूप से टेक्स्ट को अपने डेटाबेस के साथ अच्छी तरह से चलाने में रुचि रखते हैं, तो एनएफकेसी शायद एक अच्छा विकल्प है।
- यह संभावित रूप से समस्याग्रस्त पात्रों को उनके संगतता वर्णों में परिवर्तित करता है।
- फिर यह सभी वर्णों को एकल कोड बिंदुओं में संयोजित करता है।
यह देखने के लिए कि यह सुरक्षा के लिए क्यों उपयोगी है, कल्पना करें कि आपके पास "HenryIV" उपयोगकर्ता नाम वाला उपयोगकर्ता है। एक दुर्भावनापूर्ण अभिनेता एक नया उपयोगकर्ता नाम दर्ज करके इस उपयोगकर्ता को प्रतिरूपित करने का प्रयास कर सकता है:"HenryⅣ"।
मुझे पता है, वे एक जैसे दिखते हैं। यही तो बात है। लेकिन वे वास्तव में दो अलग-अलग तार हैं। पूर्व में ascii वर्णों का उपयोग किया जाता है "IV"
जबकि बाद वाला रोमन अंक 4 के लिए यूनिकोड वर्ण का उपयोग करता है:"Ⅳ"
।
आप विशिष्टता को मान्य करने से पहले स्ट्रिंग्स को सामान्य करने के लिए NFKC का उपयोग करके इस तरह की चीज़ों को रोक सकते हैं। इस मामले में, NFKC यूनिकोड "\u2163"
. को रूपांतरित करता है एएससीआई अक्षरों "IV" के लिए।
a = "Henry\u2163"
b = "HenryIV"
a.unicode_normalize(:nfc) == b.unicode_normalize(:nfc) # => false, because NFC preserves glyphs
a.unicode_normalize(:nfkc) == b.unicode_normalize(:nfkc) # => true, because NFKC evaluates both to the ascii "IV"
विभाजन शब्द
अब जब मैंने इसे और अधिक देखा है, तो मुझे आश्चर्य है कि रूबी और रेल समुदायों में यूनिकोड सामान्यीकरण एक बड़ा विषय नहीं है। आप उम्मीद कर सकते हैं कि यह आपके लिए रेल द्वारा किया जाएगा, लेकिन जहां तक मैं कह सकता हूं यह नहीं है। और आपके उपयोगकर्ताओं द्वारा आपको दिए जाने वाले डेटा को सामान्य नहीं करने का अर्थ है कि रूबी की कई स्ट्रिंग विधियाँ विश्वसनीय नहीं हैं।
यदि आप में से कोई प्रिय पाठक कुछ जानता है जो मैं नहीं जानता, तो कृपया ट्विटर @StarrHorne के माध्यम से संपर्क करें या [email protected] पर ईमेल करें। यूनिकोड एक बड़ा विषय है और मैंने पहले ही साबित कर दिया है कि मुझे इसके बारे में सब कुछ नहीं पता है। :)पी>