Menu

「日本語表現活用辞典」のインデックス再構成

【導入】
研究社の「EPWING版 日本語表現活用辞典」を購入した(データサイズ2.24MB)。語数は動詞・形容動詞 1544語と多くはなく、インデックスも前方一致表記形と後方一致表記形しかない。しかし、見出し語ごとに意味的な分 類や用法の分類があり、そのあとに例文・慣用句・複合語が合計2万5000以上収録されており、日本語のコロケーション(語と語のつながり)を見るのに役 立ちそうだ。本で見るのと同じように見出し語ごとに閲覧することもできるし、パソコンの検索ソフト(DDWinやViewIng)を使えば全文検索もでき る。Buckingham EB Playerでは、前方一致インデックスを使った完全一致検索しかできないが、それでも書籍版の「日本語表現活用辞典」と同程度の活用は可能だ。しかし、 このEPWING版には「見出し」に重大な問題があった。

【問題】

1)この辞書の見出しでは、複数の表記法があると、中点(・)で区切って列記している (例:「いく・ゆく」、「上がる・挙がる・揚がる」)。そしてこれをそのままインデックスにしている。つまり「いく」「ゆく」として別々の語で索引に挙げ るところを、「いく・ゆく」として1語で索引に登録している。これではインデックスとして機能しない。
2)パソコン上で漢字で検索すると、結果表示の見出しにかなの読みの部分は表示されない(Buckingham EB Playerでは見出しそのものが表示されない)。これは仕様なのであろうが、やはり読みも表示されたほうがいい。

【対策】
1)「前方一致表記形インデックス」中の中点で列挙されている語をすべてばらばらにし て、 インデックスを再構成する。
2)漢字のインデックスが指し示す先を、本文の見出しの先頭に書き換える。

【手順】
1)前方一致表記形インデックスのダンプ
「前方一致表記形インデックス」全体をテキスト形式におとす。
下記サイトから電子辞書解析ツール EBDump.exe をダウンロードしてインストールする。
http://www31.ocn.ne.jp/%7Eh_ishida/Others.html#lib.EBDump
EBDump を起動し、HONMON を読み込む。「メモ帳で開く」と「終了時に削 除」のチェックをはずす。「前方一致表記形INDEX」を指定し、出力ブロック数をインデックス全体(44のはず)にする。ファイル名をlog.txtに し、テキストダンプ(記述子/plain-text のどちらでも同じ)で保存する(96KB)。

2)前処理
ダンプしたインデックスから作業に不要な部分を切り捨て、中点で区切られた見出 し項目をそれぞれ単独項目に分ける。
(1) sed.exe という、テキストファイルを1行ずつ読み込みながら処理するソフト(ストリーム・エディタといいます)を下記サイトからダウンロードし、解凍する。使用す るのは フォルダの中の sed.exe だけです。日本語処理ができるものであれば、ほかのバージョンの sed でもかまわない。
http://www.vector.co.jp/soft/dos/util/se000880.html
(2) 変換用スクリプトを用意する。下記の9行を新規のテキストファイルにコピー&ペーストし、hyogen.sed という名前で保存する。

/\]\[/!d
s/\]//g
s/[\[:]/\t/g
s/\t\t/\t/
s/[英語ではルース]/・ルース/
s/(傲る)/・傲る/
:LBL
s/・\([^\t]*\)\(\t.*\)$/\2\n\1\2/
t LBL

(3) hyogen.sed、log.txt を、sed.exe と同じディレクトリにおく。MS-DOS プロンプト(コマンドプロンプト)を起動し、sed のディレクトリに移って下記を実行する。
sed -f hyogen.sed log.txt > index.txt
実行後に index.txtというファイル(88KB)ができていることを確認する。

3)前方一致表記形インデックスの書き換え
Perl のスクリプトを使い、「日本語表現活用辞典」の HONMON 中の「前方一致表記形インデックス」の内容を index.txt のデータで書き換える。
(1) Perlをインストールしていない人は、まずウェブから探してきてインストールする。
小生は、以下のサイトから ActivePerl 5.6.1.638 をインストールしました。
http://www.activestate.com/Products/Download/Download.plex?id=ActivePerl
(2) 下記の「# hyogen.pl」以降最後までを新規のテキストファイルにコピー &ペーストし、hyogen.pl という名前で保存する。
(3) perl.exe のあるディレクトリに、HONMON と index.txt と hyogen.pl をコピーする。CD-ROMからコピーした HONMON は「読み取り専用」になっているので、右クリックでプロパティを出して、「読み取り 専用」のチェックをはずす
(4) hyogen.pl をダブルクリックすると、数秒で処理が終わる。もしダブルクリックで Perl が自動起動しなかったときは、MS-DOSで Perlのディレクトリから下記のコマンドを実行する。
perl hyogen.pl
(5) 書き換わった HONMON を EBDump で読み 込み、インデックスが正常であることを確認する。

〔参考URL〕SJIS ←→ JIS 変換
http://www.d2.dion.ne.jp/~imady/charset/charcode_mame.html#SJIS_JIS

その後、必要に応じてsqueezeによる減量化や、圧縮ソフトによる処理を行う。→関連ページ
なお、オリジナルのインデックスはデータがすかすかに入っていたが、この処理では詰め たため、ファイルの末尾が20KB空いた。この空白個所をID:12の「その他のテキストデータ」として分けたので、メモリを節約したい場合は、 squeezeを使って以下を実行すると、削除され、HONMONが20KB小さくなる。(honmon.new はあとで honmon にリネームする)
squeeze -d12 honmon honmon.new


# hyogen.pl (v2)
open(HONMON, "+<honmon");
open(MAIN, "<honmon");
binmode HONMON;
binmode MAIN;
$entry=0x100;
open(INDEX, "index.txt");
@temp=<INDEX>;
@index=sort(@temp);
close(INDEX);
#ID:00
seek(HONMON, 0, 0);
read(HONMON, $tbl[0], 16);
$idno=ord(substr($tbl[0], 1, 1));
for($i=1; $i<=$idno+2; $i++){
    read(HONMON, $tbl[$i], 16);
    ($id, $a, $adr, $b, $sum)=unpack("C a3 n a2 n", $tbl[$i]);
    if ($id==0x91) {
        $id91=$i;
        $topadr=$adr;
        $lastadr=$adr+$sum-1;
        $adr1=$adr
    };
}
#ID:60
seek(HONMON, 0x0800*($adr1-1), 0);
read(HONMON, $buf, 22);
($a, $adr3)=unpack("a20 n", $buf);
# reconstruction
sub jis {
    $len=length($_[0]);
    $w="";
    for($i=0; $i<$len; $i=$i+2) {
        $code=unpack("n", substr($_[0], $i, 2));
        if ($code >= 0xE000) {$code=$code-0x4000}
        $low=$code % 256;
        $high=($code-$low) / 256;
        $high=($high-0x81)*2;
        if ($low >= 0x80) {$low=$low-1}
        if ($low >= 0x9E) {
            $code=0x2121+$high*256+$low+0x62;
        }
        else {
            $code=0x2121+$high*256+$low-0x40;
        }
        $w=$w.pack("n", $code);
    }
    $w;
}
sub output {
    local($id, $wl, $ct, $blk, $adr) = @_;
    $head=pack("CCn", $id, $wl, $ct);
    substr($blk, 0, 4)=$head;
    seek(HONMON, 0x800*($adr-1), 0);
    print HONMON $blk;
}
$id3=0xC0;
$pt=4;
$ct1=0;
$ct3=0;
$blk1=pack("x2048", );
$blk3=pack("x2048", );
while(@index) {
    $item=shift(@index);
    @k=split(/\t/,$item);
    $dlen=length($k[0])+13;
    $k0=&jis($k[0]);
    $k1=pack("C",length($k0));
    $k2=hex($k[2]);
    $k3=hex($k[3]);
    $k4=hex($k[4]);
    $k5=hex($k[5]);
        $point=0x800*($k2-1)+$k3;
        seek(MAIN, $point, 0);
        read(MAIN, $buf, 4);
        $delim=unpack("N", $buf);
        if($delim!=0x1F090002) {
            seek(MAIN, $point-$entry,0);
            read(MAIN, $buf, $entry);
            $hit=rindex($buf, pack("N", 0x1F090002));
            $new=$point-$entry+$hit;
            $k3=$new % 0x800;
            $k2=($new-$k3)/0x800+1;
        }
    $dat=$k1.$k0.pack("xxnnxxnn",$k2,$k3,$k4,$k5);
    if ($pt+$dlen > 2048) {
        &output($id3, 0, $ct3, $blk3, $adr3);
        substr($blk1, 4+18*$ct1, 18)=pack("a14xxn", $k0, $adr3);
        $ct1++;
        $pt=4;
        $adr3++;
        $blk3=pack("x2048", );
        $ct3=0;
        $id3=0x80;
    }
    substr($blk3, $pt, $dlen)=$dat;
    $pt=$pt+$dlen;
    $ct3++;
}
$ff=sprintf("%c", 0xff) x 14;
$id3=0xA0;
&output($id3, 0, $ct3, $blk3, $adr3);
substr($blk1, 4+18*$ct1, 18)=pack("a14xxn", $ff, $adr3);
$ct1++;
$id1=0x60;
&output($id1, 14, $ct1, $blk1, $adr1);
#closing
$blk3=pack("x2048", );
for($i=$adr3+1; $i<=$lastadr; $i++){
    &output(0, 0 ,0 ,$blk3, $i);
}
substr($tbl[0], 1, 1)=pack("C", $idno+1);
substr($tbl[$id91], 8, 2)=pack("n", $adr3-$topadr+1);
$tbl[$idno+2]=$tbl[$idno+1];
substr($tbl[$idno+1], 0, 10)=pack("Cxxxnxxn", 0x12, $adr3+1, $lastadr-$adr3);
seek(HONMON, 0, 0);
for($i=0; $i<=$idno+2; $i++){
    print HONMON $tbl[$i];
}
close(HONMON);
close(MAIN);