2009年06月06日 01:15 [Edit]

perl - で全角半角変換をモダンに行う

camel

今ならLingua::JA::Regular::Unicodeが第一選択肢ですが、こういう方法もあるということで。

Perl で半角カナと全角カナの変換をする : Serendip - Webデザイン・プログラミング
Perl を使って半角カタカナと全角カタカナの変換をするスクリプトを、標準モジュールの Encode.pm と Unicode::Japanese と Lingua::JA::Regular::Unicode を使ってそれぞれ変換スクリプトを書いてみる。

CORE Moduleのみを使うという縛りをかけています。

#!/usr/bin/perl                                                             
use 5.008001;
use strict;
use warnings;
use utf8;
use charnames ':full';
use Unicode::Normalize;
                                                                                
{                                                                               
    my $hankaku = "\x{FF9E}\x{FF9F}";                                           
    my $zenkaku = "\x{3099}\x{309A}";                                           
                                                                                
    for my $o (0xFF61 .. 0xFF9D){                                               
        $hankaku .= chr $o;                                                     
        my $n = charnames::viacode($o);                                         
        $n =~ s/HALFWIDTH\s+//;                                                 
        $zenkaku .= chr charnames::vianame($n);                                 
    }                                                                           
                                                                                
    *tr_h2z = eval "sub { local \$_ = shift; tr/$hankaku/$zenkaku/; \$_ }";     
    *tr_z2h = eval "sub { local \$_ = shift; tr/$zenkaku/$hankaku/; \$_ }";     
                                                                                
    sub han2zen { NFC(tr_h2z(shift)) }                                          
    sub zen2han { NFC(tr_z2h(NFD(shift))) }                                     
                                                                                
    sub hira2kata {                                                             
        local $_ = shift;                                                       
        tr/\x{3041}-\x{3096}/\x{30A1}-\x{30F6}/;                                
        $_;                                                                     
    }                                                                           
}                                                                               
binmode STDOUT, ":utf8";
local $\ = "\n";
print zen2han(hira2kata("「ぽげむたぴぎゃみにょーん」って最初に言ったのは?"));
print han2zen("ウソダドンドコドーン");


なんだか呪文じみていますが、以下を見れば何をやっているのか何となくご理解いただけるのではないでしょうか。

FF61  HALFWIDTH IDEOGRAPHIC FULL STOP
FF9D  HALFWIDTH KATAKANA LETTER N
....
FF9E  HALFWIDTH KATAKANA VOICED SOUND MARK
FF9F  HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK

3099  COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
309A  COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK

3041  HIRAGANA LETTER SMALL A
....
3096  HIRAGANA LETTER SMALL KE

30A1  KATAKANA LETTER SMALL A
....
30F6  KATAKANA LETTER SMALL KE

半?濁点の処理を、Unicode::Normalizeでやっているのが工夫のしどころでしょうか。

で、業務連絡>id:tokuhirom。

Lingua::JA::Regular::Unicode というモジュールをつくりました - TokuLog 改めB日記
同じことができるモジュールとして id:takefumi 作の Lingua::JA::Regular というものがあるのですが、これは EUC-JP 前提なので、昨今の「内部コードは flagged utf8」という流れからすると、無駄に二回文字コードの変換をはしらせなくてはならず、使いづらかったので、新たに unicode 前提でつくりなおしました。

Lingua::JA::Regular::Unicodeの中味は正しくtr///のお化けなのですが、残念なことに、Perl 5.8.0のtr///はUnicode的にbuggyで非推奨です。CodeReposのrepoは直しておいたので、あとはよろしくです。あと、Module::Installを使っているのはモダンで結構なのですが、CodeReposの方にincディレクトリがなくて、trunkから直にperl Makefile.PLできなくなっているようです。CPANの方はOKなのですが。

これに限らず、Unicode-savvyなPerlの事実上の最古Versionは5.8.1と覚えておくとよいでしょう。

ダンザパールモンガー


この記事へのトラックバックURL

この記事へのトラックバック
おばけなんてないさ おばけなんてうそさ ねぼけたひとが みまちがえたのさ
perl でカタカナ及び記号の全角半角変換をモダン?に行う【talk to oneself 2】at 2010年09月26日 18:45
"Perl で半角カナと全角カナの変換をする" の記事を書いたら、"404 Blog Not Found:perl - で全角半角変換をモダンに行う" という CORE Module のみを使う方法というのが返ってきたの...
Perl で全角半角変換をモダンに行うコードを理解する【Serendip】at 2009年06月07日 17:06
ぐぐっても、変換コードがありそうでなかったのでついでに。 404 Blog Not Found:perl - で全角半角変換をモダンに行う
javascript - でも全角半角変換【404 Blog Not Found】at 2009年06月06日 15:35
この記事へのコメント
すみません、どこに書いていいかわからなかったのでここに書いておきます。

"\x{0100}=ccc" =~ /.*?=(a|b)/;

で、Malformed UTF-8 character エラーになります。
バージョンは 5.8.8, 5.10.0 の両方。
Posted by 挧 at 2009年06月09日 00:03
まったくわかりません!!wwwwww

馬鹿でもうしわけありません!!

(´・ω・`)ショボーン
Posted by けんじ at 2009年06月06日 04:16