このエントリを書いた人間はUnicodeや中国語について素人です。
このエントリに載っている情報は誤っている可能性があります。
結論
厳密では無いが、Unicode Han Database(Unihan)を参照して広東語または北京語の発音を持ち
かつ音読みまたは訓読みの発音を持たない文字
が含まれているかどうかで判定できそうだ。
概要
- 最初に試みた方法:
- 「
/[ぁ-ん]/
にマッチする文字列を取り出すことでひらがなのみが取り出せるように、中国語のみを正規表現で取り出せないか」。 - Unicode上で漢字は、中国語・日本語・朝鮮語で使われている漢字をひとまとめにした
CJK統合漢字
という概念で扱われているので無理だった。 - https://ja.wikipedia.org/wiki/CJK%E7%B5%B1%E5%90%88%E6%BC%A2%E5%AD%97
- 「
- Unihanには、ある漢字の
読みの情報
が含まれている。- 「中国語読みがあって、かつ、日本語読みが無い漢字」が含まれていればたぶん中国語であろう、という事が言える。
- そのように実装してみたら、期待したように動いた。
実装
1. Unihanから漢字とその読みの対応表
を取ってくる。
ここにあるUnihan.zip
のUnihan_Readings.txt
を取ってくる。
http://www.unicode.org/Public/UNIDATA/
2. ファイルを分割する
以下のように分割する。
- 訓読みがあるcodepointだけを集めたファイル
- 音読みがあるcodepointだけを集めたファイル
- 北京語読みがあるcodepointだけを集めたファイル
- 広東語みがあるcodepointだけを集めたファイル
具体的にはこうする。
cat Unihan_Readings.txt | awk '$2 ~ /kJapaneseKun/ {print $1}' > japanese_kun cat Unihan_Readings.txt | awk '$2 ~ /kJapaneseOn/ {print $1}' > japanese_on cat Unihan_Readings.txt | awk '$2 ~ /kMandarin/ {print $1}' > mandarin cat Unihan_Readings.txt | awk '$2 ~ /kCantonese/ {print $1}' > cantonese
3. ある文字が、2.で作ったどのファイルに含まれるかで判定する
広東語または北京語の発音を持ち
かつ音読みまたは訓読みの発音を持たない文字
が含まれている文字だけを取り出すプログラムを書く。
具体的にはこうする。
補足:
- ruby
- 一番下に実行例が書いてある
# maybe_chinese.rb CODEPOINTS = { japanese_kun: File.read('japanese_kun'), japanese_on: File.read('japanese_on'), cantonese: File.read('cantonese'), mandarin: File.read('mandarin'), }.freeze # size == 1のStringをcodepointに変換する def to_codepoint(character) #raise "size == 1のStringを与える必要がある" unless character.size == 1 character.codepoints.map{|cp| sprintf("%04X", cp)}.first end # 以下のように書きたいところだが重いので正規表現でやる # CODEPOINTS[:japanese_kun].include?(codepoint) # (CODEPOINTS[:japanese_kun]を配列にしておいた上で) def japanese_kun?(codepoint) !!(CODEPOINTS[:japanese_kun] =~ /\nU\+#{codepoint}\n/) end def japanese_on?(codepoint) !!(CODEPOINTS[:japanese_on] =~ /\nU\+#{codepoint}\n/) end def cantonese?(codepoint) !!(CODEPOINTS[:cantonese] =~ /\nU\+#{codepoint}\n/) end def mandarin?(codepoint) !!(CODEPOINTS[:mandarin] =~ /\nU\+#{codepoint}\n/) end # 漢字か判定 def han?(character) character =~ /\p{Han}/ end # 文字列から中国語らしき文字をselectする。 # なぜか漢字以外のcodepointを与えると期待した動作をしないので、漢字のみで判定する。 def select_chinese_and_not_japanese(survey_target_string) survey_target_string.split('').select do |character| next if !han?(character) codepoint = to_codepoint(character) next if japanese_kun?(codepoint) || japanese_on?(codepoint) next if !(cantonese?(codepoint) || mandarin?(codepoint)) true end end
実行例
p select_chinese_and_not_japanese("我开动了, 多谢款待") #=> ["开", "动", "谢"] # 日本語としての読みを持つ字は引っかからない p select_chinese_and_not_japanese("简体字") #=> ["简"] # 日本語としての読みを持つ字は引っかからない p select_chinese_and_not_japanese("日本語") #=> [] p select_chinese_and_not_japanese("ひらがなabc,.") #=> []
課題
- この実装だと「たまたま音読みor訓読みを持つ中国語の漢字のみで構成された文字列」は中国語だと判定されなくなってしまう。
- 今回の(私が必要としていた)ユースケースだと別に問題なかったので無視した。