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

时间:2011-01-13 14:22:25

标签: ruby unicode encoding character-encoding cjk

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

4 个答案:

答案 0 :(得分:42)

(红宝石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 {}匹配角色的Unicode脚本 支持以下脚本:阿拉伯语,亚美尼亚语,巴厘岛语,孟加拉语,Bopomofo,盲文,Buginese,Buhid,Canadian_Aboriginal,Carian,Cham,Cherokee,Common,Coptic,Cuneiform,Cypriot,Cyrillic,Deseret,Devanagari,Ethiopic,Georgian,Glagolitic, Gothic,Greek,Gujarati,Gurmukhi,Han,Hangul,Hanunoo,Hebrew,Hiragana,Inherited,Kannada,Katakana,Kayah_Li,Kharoshthi,Khmer,Lao,Latin,Lepcha,Limbu,Linear_B,Lycian,Lydian,Malayalam,Mongolian,Myanmar, 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 source

答案 1 :(得分:9)

鉴于我的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黑客做好准备。

答案 2 :(得分:1)

我写了一个小宝石,在steenslag的答案中包含了这个方法:

https://github.com/jpatokal/script_detector

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

答案 3 :(得分:0)

基于this code的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