如何在Ruby中检测字符串中的某些Unicode字符?

给定Ruby 1.8.7中的字符串(没有使用\ p {}支持Unicode属性的令人敬畏的Oniguruma正则表达式引擎),我希望能够确定该字符串是否包含一个或多个中文,日文或韩文字符; 即

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块中 ,但我认为值得询问是否有人知道Ruby中的现有解决方案。

(ruby1.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 {}匹配角色的Unicode脚本。
支持以下脚本:阿拉伯语,亚美尼亚语,巴厘语,孟加拉语,Bopomofo,盲文,Buginese,Buhid,Canadian_Aboriginal,Carian,Cham,Cherokee,Common,Coptic,Cuneiform,Cypriot,Cyrillic,Deseret,Devanagari,Ethiopic,Georgian,Glagolitic,哥特式,希腊语,古吉拉特语,Gurmukhi,汉语,朝鲜语,Hanunoo,希伯来语,平假名,inheritance,卡纳达语,片假名,Kayah_Li,Kharoshthi,高棉语,老挝语,拉丁语,Lepcha,Limbu,Linear_B,利西亚语,Lydian,马拉雅拉姆语,蒙古语,缅甸语, New_Tai_Lue,Nko,Ogham,Ol_Chiki,Old_Italic,Old_Persian,Oriya,Osmanya,Phags_Pa,Phoenician,Rejang,Runic,Saurashtra,Shavian,Sinhala,Sundanese,Syloti_Nagri,Syriac,Tagalog,Tagbanwa,Tai_Le,Tamil,Telugu,Thaana,Thai,西藏人,Tifinagh,Ugaritic,Vai和Yi。

哇。 Ruby Regexp源码 。

鉴于我的Ruby 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 

非常朴素,但它的工作原理。 它实际上也会检测各种印度语脚本,所以它应该真正被称为contains_asian?

也许我应该为其他陷入Ruby 1.8的可怜的I18N黑客做好准备。

我写了一个小gem,在steenslag上面的答案中包含了这个方法:

https://github.com/jpatokal/script_detector

它也可以用来区分日语,韩语,简体中文和繁体中文,但由于汉族统一的复杂性,它只能在大块文本中可靠地工作。

Ruby 1.8解决方案基于此代码并使用Josh Glover在此线程上的解决方案的API:

 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