tokenize_by_script 這個函式
作者:gugod 發佈於: #code #perl一陣子之前隨意把一些處理中文的字串處理函式打包成 Text::Util::Chinese 模組釋出了。其中包含一個函式名為 tokenize_by_script 。
這個函式的主要功用是將一個字串依每個字符之 Script 屬性值切開成多個單位。例如這個混合多語言的字串,「池袋這個地名寫成日語假名為イケブクロ,英譯為Ikebukuro,但如果向人問路時唸成ㄔˊㄉㄞˋ反而沒人聽得懂。」,會被切開成這 13 段:
- 池袋這個地名寫成日語假名為
 - イケブクロ
 - ,
 - 英譯為
 - Ikebukuro
 - ,
 - 但如果向人問路時唸成
 - ㄔ
 - ˊ
 - ㄉㄞ
 - ˋ
 - 反而沒人聽得懂
 - 。
 
會需要這種函式,主要是因爲在處理多語言混合文字時,通常同一種書寫系統(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 這個資料集的介面之一。