Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी में यूनिकोड सामान्यीकरण

मैंने हाल ही में एक लेख प्रकाशित किया जिसमें मैंने कुछ यूनिकोड वर्णों के साथ रूबी की अधिकांश स्ट्रिंग विधियों का परीक्षण किया ताकि यह देखने के लिए कि वे अप्रत्याशित रूप से व्यवहार करेंगे या नहीं। उनमें से कई ने किया।

एक आलोचना जो कुछ लोगों ने लेख की थी वह यह थी कि मैं परीक्षण के लिए असामान्य तारों का उपयोग कर रहा था। सच कहूँ तो, मैं यूनिकोड सामान्यीकरण पर थोड़ा फजी था। मुझे संदेह है कि कई रूबी वादक हैं।

सामान्यीकरण का उपयोग करके, आप कई यूनिकोड स्ट्रिंग्स ले सकते हैं जो मेरे परीक्षणों में अप्रत्याशित रूप से व्यवहार करते हैं और उन्हें स्ट्रिंग्स में परिवर्तित करते हैं जो रूबी की स्ट्रिंग विधियों के साथ अच्छी तरह से खेलते हैं। हालांकि:

  1. रूपांतरण हमेशा सही नहीं होता है। कुछ यूनिकोड अनुक्रम हमेशा रूबी की स्ट्रिंग विधियों को गलत व्यवहार करने का कारण बनते हैं।
  2. यह कुछ ऐसा है जो आपको मैन्युअल रूप से करना है। डिफ़ॉल्ट रूप से न तो रूबी, न ही रेल और न ही डीबी स्वचालित रूप से सामान्य हो जाती है।

यह लेख रूबी में यूनिकोड सामान्यीकरण का एक संक्षिप्त परिचय होगा। उम्मीद है कि यह आपको अपने स्वयं के अन्वेषणों के लिए एक महत्वपूर्ण बिंदु प्रदान करेगा।

आइए एक स्ट्रिंग को सामान्य करें

<ब्लॉकक्वॉट>

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 के माध्यम से संपर्क करें या starr@honeybadger.io पर ईमेल करें। यूनिकोड एक बड़ा विषय है और मैंने पहले ही साबित कर दिया है कि मुझे इसके बारे में सब कुछ नहीं पता है। :)

  1. रूबी में लैम्ब्डा का उपयोग करना

    ब्लॉक रूबी का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना मुश्किल है। लेकिन लैम्ब्डा? लैम्ब्डा को कौन प्यार करता है? आप एक का उपयोग किए बिना वर्षों तक जा सकते हैं। वे लगभग पुराने जमाने के अवशेष की तरह लगते हैं। ...लेकिन यह बिल्कुल सच नहीं है। एक बार जब आप उनकी थोड़ी जांच कर लेते हैं त

  1. रूबी में इंसर्शन सॉर्ट को समझना

    नोट:रूबी के साथ विभिन्न सॉर्टिंग एल्गोरिदम को लागू करने पर विचार करने वाली श्रृंखला में यह भाग 4 है। भाग 1 ने बबल सॉर्ट की खोज की, भाग 2 ने चयन प्रकार की खोज की, और भाग 3 ने मर्ज सॉर्ट की खोज की। जैसा कि हम डेटा सॉर्ट करने के लिए विभिन्न तरीकों का पता लगाना जारी रखते हैं, हम इंसर्शन सॉर्ट की ओर रु

  1. रूबी में 9 नई सुविधाएँ 2.6

    रूबी का एक नया संस्करण नई सुविधाओं और प्रदर्शन में सुधार के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज रूबी 2.5 और पुराने संस्करण पहले से ही अंतहीन श्रेणी के एक रूप का समर्थन करते हैं (Float::INFINITY के साथ) ), लेकिन रूबी 2.6 इसे अगले स्तर पर ले