2012-10-05 21 views
9

मैं पाइथन 2.7.3 में re मॉड्यूल का उपयोग करने का प्रयास कर रहा हूं जिसमें यूनिकोड एन्कोडेड देवनागरी पाठ है। मैंने अपने कोड के शीर्ष पर from __future__ import unicode_literals जोड़ा है, इसलिए सभी स्ट्रिंग्स अक्षर यूनिकोड ऑब्जेक्ट्स होना चाहिए।पायथन यूनिकोड नियमित अभिव्यक्ति मिलान कुछ यूनिकोड वर्णों के साथ विफल रहा है -बग या गलती?

हालांकि, मैं पाइथन के रेगेक्स मिलान के साथ कुछ विषम समस्याओं में भाग रहा हूं। उदाहरण के लिए, इस नाम पर विचार करें: "किशोरी"। यह हिंदी में एक (गलत वर्तनी) नाम है, जो मेरे उपयोगकर्ताओं में से एक द्वारा दर्ज किया गया है। कोई हिंदी पाठक इसे एक शब्द के रूप में पहचान लेगा।

निम्नलिखित एकदम सही ढंग से, एक मैच रिटर्न:

re.search("^[\w\s][\w\s]*","किशोरी",re.UNICODE)

लेकिन यह नहीं करता है:

re.search("^[\w\s][\w\s]*$","किशोरी",re.UNICODE)

कुछ spelunking पता चला है कि इस स्ट्रिंग में केवल एक ही चरित्र, चरित्र 0915 (क), \ w चरित्र वर्ग के भीतर गिरने के रूप में पहचाना जाता है। यह गलत है, क्योंकि यूनिकोड कैरेक्टर डाटाबेस file on "derived core properties" इस स्ट्रिंग में वर्णमाला के रूप में अन्य वर्णों (मैंने सभी की जांच नहीं की है) सूचीबद्ध की है - वास्तव में वे हैं।

क्या यह पाइथन के कार्यान्वयन में बस एक बग है? मैं चरित्र के रूप में सभी देवनागरी अल्फान्यूमेरिक वर्णों को मैन्युअल रूप से परिभाषित करके इसे प्राप्त कर सकता हूं, लेकिन यह दर्दनाक होगा। या मुझ से कुछ गलत हो रहा है?

उत्तर

7

यह एक bug in the re module है और यह regex module में तय हो गई है:

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 
import unicodedata 
import re 
import regex # $ pip install regex 

word = "किशोरी" 


def test(re_): 
    assert re_.search("^\\w+$", word, flags=re_.UNICODE) 

print([unicodedata.category(cp) for cp in word]) 
print(" ".join(ch for ch in regex.findall("\\X", word))) 
assert all(regex.match("\\w$", c) for c in ["a", "\u093f", "\u0915"]) 

test(regex) 
test(re) # fails 

उत्पादन से पता चलता "किशोरी" में 6 कोड पॉइंट्स हैं, लेकिन केवल 3 उपयोगकर्ता के कथित वर्ण (बढ़ाया ग्रफीम समूहों) देखते हैं कि। एक शब्द को के अंदर एक शब्द तोड़ना गलत होगा।Unicode Text Segmentation का कहना है:

वर्ड सीमाओं, लाइन सीमाओं, और वाक्य सीमाओं एक ग्रफीम क्लस्टर के भीतर हो नहीं करना चाहिए: दूसरे शब्दों में, एक ग्रफीम क्लस्टर प्रक्रिया के संबंध में एक परमाणु इकाई होना चाहिए इन अन्य सीमाओं को निर्धारित करने के लिए।

यहाँ और आगे जोर मेरा है

एक शब्द सीमा \b\w से करने के लिए \Wthe docs में (या रिवर्स में) एक संक्रमण के रूप में परिभाषित किया गया है:

ध्यान दें कि औपचारिक रूप से, \ बी को \ w और \ W वर्ण (या इसके विपरीत) के बीच की सीमा के रूप में परिभाषित किया गया है, या \ w और स्ट्रिंग के प्रारंभ/अंत के बीच सीमा ...

इसलिए या तो सभी कोड पॉइंट्स कि एक चरित्र के रूप में \w हैं या वे सभी \W हैं। इस मामले में "किशोरी" मैचों ^\w{6}$


the docs for \w in Python 2 से:

यूनिकोड सेट है, तो इस से मेल खाएगी वर्ण [0-9_] प्लस जो कुछ यूनिकोड वर्ण गुण डेटाबेस में अक्षरांकीय के रूप में वर्गीकृत किया जाता है।

Python 3 में

:

मेल यूनिकोड शब्द पात्रों; यह में अधिकांश वर्ण शामिल हैं जो किसी भी भाषा, साथ ही संख्याओं और अंडरस्कोर में किसी भी शब्द का हिस्सा हो सकते हैं।

regex से डॉक्स:

'शब्द' चरित्र (issue #1693050) की परिभाषा:

एक 'शब्द' चरित्र की परिभाषा यूनिकोड के लिए विस्तार किया गया है। यह अब http://www.unicode.org/reports/tr29/ पर यूनिकोड विनिर्देश के अनुरूप है।यह \ w, \ W, \ b और \ B पर लागू होता है।

unicode.org U+093F (DEVANAGARI VOWEL SIGN I) के अनुसार तो regex भी यह \w विचार करने के लिए भले ही हम परिभाषाओं कि शब्द सीमाओं पर आधारित नहीं हैं का पालन सही है alnum और अक्षर है।

+0

हां, पुष्टि कर सकते हैं कि regex मॉड्यूल काम करता है। [[: Alnum:]] POSIX चरित्र वर्ग भी regex मॉड्यूल के साथ काम करता है। – ShankarG

+0

@ शंकर जी: 'perl' सहमत हैं: 'echo किशोरी | perl -CS -ne'print अगर/^ \ w + $/''(utf-8 io मानें)। – jfs

+0

इस उत्तर में मेरा "स्वीकृत" चिह्न बदल गया, क्योंकि यह वास्तव में सही उत्तर है - यह वास्तव में पुनः मॉड्यूल में एक बग है। – ShankarG

3
वर्ण मानचित्र से

:

ि

U + 093F देवनागरी स्वर इन मैं

जनरल चरित्र गुण

यूनिकोड में के बाद से: 1.1 यूनिकोड श्रेणी: मार्क, रिक्ति

का संयोजन

तो तकनीकी रूप से यह एक पत्र नहीं है और के तहत भी re.UNICODE के साथ नहीं आता है। आप इस प्रकार के पात्रों को शामिल करने के लिए यूनिकोड चरित्र गुणों के साथ regex का उपयोग करने का प्रयास कर सकते हैं।

+0

[सूची जो मैंने उपरोक्त व्युत्पन्न कोड गुणों से जुड़ी सूची] के अनुसार [http://www.unicode.org/Public/UNIDATA/DerivedCoreProperties.txt) 093F को वास्तव में वर्णमाला वर्ण के रूप में वर्गीकृत किया गया है। निशचित तौर पर मालूम नहीं कया हो रहा है। किसी भी मामले में, इन्हें इस तरह पहचाना जाना चाहिए - ये पात्र कभी भी अपने आप पर खड़े नहीं होते हैं, वे मौजूदा स्वरों के संकेतों को इंगित करने के लिए मौजूदा वर्णों में संशोधन कर रहे हैं (इस मामले में चरित्र इंगित करता है कि बाद में "का" को " की ")। – ShankarG

+0

यदि कोई इन वर्णों और वर्णमालाओं को वर्णमाला वर्णों के रूप में अस्वीकार कर रहा था, तो इसका उपयोग करने वाली किसी भी भाषा में हिंदी, बंगाली, मराठी इत्यादि में देवनागरी पाठ कभी भी प्रकृति में वर्णमाला के रूप में पहचाना नहीं जाएगा। – ShankarG

+0

"093E..0940; वर्णमाला # मैक [3] देवनागरी वावेल साइन एए..देवंगारी वावेल साइन II" मैक। ** Mc **। –

2

मैं परीक्षण किया है:

import unicodedata 
for c in "किशोरी": 
    print unicodedata.category(c) 
    print unicodedata.name(c) 

जो मेरे मामले में प्रदर्शित करता है:

Lo 
DEVANAGARI LETTER KA 
Mc 
DEVANAGARI VOWEL SIGN I 
Lo 
DEVANAGARI LETTER SHA 
Mc 
DEVANAGARI VOWEL SIGN O 
Lo 
DEVANAGARI LETTER RA 
Mc 
DEVANAGARI VOWEL SIGN II 

यूनिकोड सामान डिबग करने के लिए क्योंकि कॉपी और पेस्ट कर सकते हैं डेटा गंदगी और मैं नहीं जानता कि कठिन है हिंदी। लेकिन कुछ भाषाओं में आप यूनिकोड में विभिन्न तरीकों से पात्रों को एन्कोड कर सकते हैं। क्या यह संभव है, कि आपको मिलान करने से पहले किसी भी तरह अपनी स्ट्रिंग को सामान्य बनाना होगा? मेरे लिए यह ठीक दिखता है कि एक स्वर संकेत \w से मेल नहीं खाता है।

+0

नीचे इग्नासिओ के उत्तर पर टिप्पणी देखें। सामान्यीकरण करके आपका क्या मतलब है, यद्यपि? शायद वह चाल करेगा। – ShankarG

+0

मुझे अपने सिर से सटीक विवरण याद नहीं हैं, लेकिन वहां एक पात्र हैं जो स्वयं पर मौजूद हैं और यह भी एक संयोजन हो सकता है। उदाहरण के लिए जर्मन 'ä'। यह एक ही चरित्र है, लेकिन जहां तक ​​मुझे पता है कि इसे उस बिंदु पर रखने के लिए 'ए' + मार्कर' के रूप में एन्कोड करने की संभावना है। और दोनों संस्करणों के बीच एक परिवर्तन है। क्षमा करें, मुझे इस समय विवरण की जांच करने की कोई संभावना नहीं है। – Achim

संबंधित मुद्दे