tokenize_by_script 這個函式

作者:   發佈於:   #code #perl

一陣子之前隨意把一些處理中文的字串處理函式打包成 Text::Util::Chinese 模組釋出了。其中包含一個函式名為 tokenize_by_script

這個函式的主要功用是將一個字串依每個字符之 Script 屬性值切開成多個單位。例如這個混合多語言的字串,「池袋這個地名寫成日語假名為イケブクロ,英譯為Ikebukuro,但如果向人問路時唸成ㄔˊㄉㄞˋ反而沒人聽得懂。」,會被切開成這 13 段:

  1. 池袋這個地名寫成日語假名為
  2. イケブクロ
  3. 英譯為
  4. Ikebukuro
  5. 但如果向人問路時唸成
  6. ˊ
  7. ㄉㄞ
  8. ˋ
  9. 反而沒人聽得懂

會需要這種函式,主要是因爲在處理多語言混合文字時,通常同一種書寫系統(Script)的處理方式是類似的。只要是拉丁文字,無論寫的是英文或是荷蘭文,大致上的初步處理就是先依照空白切開,只要是漢字,無論是日文或是中文,多半需要依詞典分詞或是做 bigram。

就算是書寫中文,注音符號的處理規則也與漢字不同,多半不必做 bigram。片假名與平假名這兩種表音符號也是。

這個函式全文如下(Perl 版):

use Unicode::UCD qw(charscript);

sub tokenize_by_script {
    my ($str) = @_;
    my @tokens;
    my @chars = grep { defined($_) } split "", $str;
    return () unless @chars;
 
    my $t = shift(@chars);
    my $s = charscript(ord($t));
    while(my $char = shift @chars) {
        my $_s = charscript(ord($char));
        if ($_s eq $s) {
            $t .= $char;
        }
        else {
            push @tokens, $t;
            $s = $_s;
            $t = $char;
        }
    }
    push @tokens, $t;
    return grep { ! /\A\s*\z/u } @tokens;
}

每個字符的屬性之取得是以 charscript 這個來自 Unicode::UCD 模組的函式來完成。這函式是 Unicode Character Database 這個資料集的介面之一。