2011-01-13 10 views
16

रुबी 1.8.7 में एक स्ट्रिंग को देखते हुए (अद्भुत ओनिगुरुमा नियमित अभिव्यक्ति इंजन के बिना जो यूनिकोड गुणों को \ p {} के साथ समर्थन करता है), मैं यह निर्धारित करने में सक्षम होना चाहूंगा कि स्ट्रिंग में एक या अधिक चीनी, जापानी या कोरियाई वर्ण; अर्थातरूबी में एक स्ट्रिंग में कुछ यूनिकोड वर्णों का पता कैसे लगा सकता हूं?

class String 
    def contains_cjk? 
    ... 
    end 
end 

>> '日本語'.contains_cjk? 
=> true 
>> '광고 프로그램'.contains_cjk? 
=> true 
>> '艾弗森将退出篮坛'.contains_cjk? 
=> true 
>> 'Watashi ha bakana gaijin desu.'.contains_cjk? 
=> false 

मुझे लगता है कि यह देख अगर स्ट्रिंग में वर्णों की किसी भी Unihan CJKV Unicode blocks में हैं करने के लिए नीचे उबल पड़ेगी, लेकिन मुझे लगा कि यह किसी रूबी में एक मौजूदा समाधान के जानता है पूछ लायक था।

+0

आप अच्छा यूनिकोड regex समर्थन के बिना रूबी के संस्करण 1.9, या सिर्फ एक पुराने संस्करण का उपयोग कर रहे हैं? यदि आप 1.9 का उपयोग कर रहे हैं, तो आपको (कुछ) यूनिकोड गुणों तक पहुंच प्राप्त करनी चाहिए, जैसे '\ p {InCJKUnifiedIdeographs} 'या शायद' \ p {Han} '। ओनिगुरुमा के बिना – tchrist

+0

1.8.7; सवाल अद्यतन किया। –

उत्तर

39

(रूबी 1.9.2)

#encoding: UTF-8 
class String 
    def contains_cjk? 
    !!(self =~ /\p{Han}|\p{Katakana}|\p{Hiragana}|\p{Hangul}/) 
    end 
end 

strings= ['日本', '광고 프로그램', '艾弗森将退出篮坛', 'Watashi ha bakana gaijin desu.'] 
strings.each{|s| puts s.contains_cjk?} 

#true 
#true 
#true 
#false 

\ p {} एक वर्ण का यूनिकोड स्क्रिप्ट से मेल खाता है।
निम्नलिखित स्क्रिप्ट समर्थित हैं: अरबी, अर्मेनियाई, बालिनीज, बंगाली, बोपोमोफो, ब्रेल, बगिनीस, बुहिद, कनाडाई_एबोरिजिनल, कैरियन, चाम, चेरोकी, कॉमन, कॉप्टिक, क्यूनिफॉर्म, साइप्रोट, सिरिलिक, डिसेरेट, देवनागरी, इथियोपिक, जॉर्जियाई, ग्लैगोलिटिक, गोथिक, ग्रीक, गुजराती, गुरुमुखी, हान, हंगुल, हनुनू, हिब्रू, हिरगाना, विरासत, कन्नड़, कटाकाना, कायह_ली, खरोशथी, खमेर, लाओ, लैटिन, लेपचा, लिंबू, लीनारबी, लिसीन, लिडियन, मलयालम, मंगोलियाई, म्यांमार, न्यू_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, उड़िया, ओस्मानिया, Phags_Pa, फोनीशियन, रेजांग, रूनिक, सौराष्ट्र, शावियन, सिंहला, सुंडानी, Syloti_Nagri, सिरिएक, तागालोग, टैगबानवा, Tai_Le, तमिल, तेलुगू, Thaana, थाई, तिब्बती, तिफिनघ, उगारिटिक, वाई, और यी।

वाह। Ruby Regexp source

+0

यह निश्चित रूप से रूबी 1.9, या रूबी 1.8 में ओनिगुरुमा रेगेक्स इंजन के साथ काम करता है। मैं ओनिगुरुमा के बिना 1.8.7 का उपयोग कर रहा हूं। :( ग्रेट सॉल्यूशन, भले ही यह इस विशेष मामले में मेरी मदद नहीं करता है। –

+2

मुझे यह काम करने के लिए फ़ाइल के शीर्ष पर '# एन्कोडिंग: यूटीएफ -8' जोड़ना पड़ा। अन्यथा मुझे एक अवैध चरित्र संपत्ति मिली नाम त्रुटि – Morrowless

+1

'[पी {हान} \ पी {कटाकाना} \ p {हिरगाना} \ p {हंगुल}] करने के लिए और अधिक समझ में आता है। – tchrist

9

मेरी रूबी 1.8.7 बाधा को देखते हुए, यह सबसे अच्छा मैं कर सकता है:

class String 
    CJKV_RANGES = [ 
     (0xe2ba80..0xe2bbbf), 
     (0xe2bfb0..0xe2bfbf), 
     (0xe38080..0xe380bf), 
     (0xe38180..0xe383bf), 
     (0xe38480..0xe386bf), 
     (0xe38780..0xe387bf), 
     (0xe38880..0xe38bbf), 
     (0xe38c80..0xe38fbf), 
     (0xe39080..0xe4b6bf), 
     (0xe4b780..0xe4b7bf), 
     (0xe4b880..0xe9bfbf), 
     (0xea8080..0xea98bf), 
     (0xeaa080..0xeaaebf), 
     (0xeaaf80..0xefbfbf), 
    ] 

    def contains_cjkv? 
    each_char do |ch| 
     return true if CJKV_RANGES.any? {|range| range.member? ch.unpack('H*').first.hex } 
    end 
    false 
    end 
end 


strings = ['日本', '광고 프로그램', '艾弗森将退出篮坛', 'Watashi ha bakana gaijin desu.'] 
strings.each {|s| puts s.contains_cjkv? } 

#true 
#true 
#true 
#false 

सुंदर hacktacular, लेकिन यह काम करता है। यह वास्तव में विभिन्न इंडिक स्क्रिप्ट्स का भी पता लगाता है, इसलिए इसे शायद वास्तव में include_asian कहा जाना चाहिए?

शायद मुझे रूबी 1.8 के साथ फंस गए अन्य गरीब I18N हैकर्स के लिए इसे याद रखना चाहिए।

+0

मैं दूसरों यह सहायक लग सकता है लगता है। – Geo

+0

मैं एक परियोजना भी 1.8 पर अटक गए हैं। यह समाधान मेरे लिए काम नहीं किया, लेकिन मैं एक और स्टैक ओवरफ़्लो धागे से एक समाधान अनुकूलित - यहाँ मेरा उत्तर देखें। –

1

मैं एक छोटे से मणि है कि इसके बाद के संस्करण steenslag के जवाब में दृष्टिकोण पैकेज लिखा है:

https://github.com/jpatokal/script_detector

यह भी जापानी, कोरियाई, सरलीकृत चीनी और पारंपरिक चीनी के बीच अंतर करने में एक चाकू ले जा सकते हैं, हालांकि हान एकीकरण की जटिलताओं के कारण यह केवल टेक्स्ट के बड़े स्लैब के साथ विश्वसनीय रूप से काम करता है।

0

रूबी 1.8 समाधान this code पर आधारित है और इस सूत्र पर जोश ग्लोवर के समाधान से एपीआई का उपयोग कर:

class String 
    CJKV_RANGES = [ 
    (0x4E00..0x9FFF), 
    (0x3400..0x4DBF), 
    (0x20000..0x2A6DF), 
    (0x2A700..0x2B73F), 
    ] 

    def contains_cjkv? 
    unpack("U*").any? { |char| 
     CJKV_RANGES.any? { |range| range.member?(char) } 
    } 
    end 
end 
संबंधित मुद्दे

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