strings regexp palabras numeros mayusculas hacer funcion contar comparar como cadenas ruby unicode encoding character-encoding cjk

regexp - ¿Cómo puedo detectar ciertos caracteres Unicode en una cadena en Ruby?



regexp match ruby (4)

Dada una cadena en Ruby 1.8.7 (sin el asombroso motor de expresión regular Oniguruma que admite las propiedades Unicode con / p {}), me gustaría poder determinar si la cadena contiene uno o más caracteres chinos, japoneses o coreanos; es decir

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

Sospecho que esto se reducirá a ver si alguno de los caracteres de la cadena está en los bloques Unicode CJKV Unicode , pero pensé que valía la pena preguntar si alguien sabe de una solución existente en Ruby.


Dada mi restricción de Ruby 1.8.7, esto es lo mejor que puedo hacer:

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

Bastante hacktacular, pero funciona. En realidad, también detecta una variedad de scripts de Indic, por lo que probablemente debería llamarse contains_asian.

Tal vez debería joder esto para otros hackers I18N pobres atrapados con Ruby 1.8.


He escrito una pequeña joya que empaqueta el enfoque en la respuesta de steenslag anterior:

https://github.com/jpatokal/script_detector

También puede ser difícil diferenciar entre japonés, coreano, chino simplificado y chino tradicional, aunque debido a las complejidades de la unificación de Han, solo funciona de manera confiable con grandes bloques de texto.


(ruby 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 {} coincide con la secuencia de comandos Unicode de un personaje.
Los siguientes guiones son compatibles: árabe, armenio, balinés, bengalí, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, común, copto, cuneiforme, chipriota, cirílico, Deseret, Devanagari, etíope, georgiano, glagolítico, Gótico, Griego, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebreo, Hiragana, Heredado, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latín, Lepcha, Limbu, Linear_B, Licio, Lidio, Malayalam, Mongol, 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, tailandés, Tibetano, Tifinagh, Ugaritic, Vai y Yi.

Guau. Fuente Ruby Regexp .


Solución de Ruby 1.8 basada en este código y usando la API de la solución de Josh Glover en este hilo:

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