はじめに
前記事,MATLABでmecab-ipadic-NEologdをシステム辞書として使うを書いた後で,「辞書のビルドをするのに,特定のファイルをコピーしたり,その一部だけをコード変換したりという手続きが面倒臭いなぁ,MATLABから一発でできないかなぁ」などと思いながらMATLABドキュメントの森を探索しているうちに,何とかなりそうだったのでやってみたら何とかなっちゃいました.
鍵は辞書ファイルのコード変換.下の例では,ファイルfileToConvet.csv
を開いてShift-JISからUTF-8へコード変換して,上書き保存してます.これができれば後はスクリプトを普通に書くだけなので,大事な部分はここまで.
filePath = 'fileToConvert.csv';
% ファイルの中身を全部読み込んで
fid = fopen(filePath,'r');
tmpChar = fread(fid);
fclose(fid);
% この1行でコード変換
tmpChar = unicode2native(native2unicode(tmpChar,'Shift-JIS'),'UTF-8');
% 上書き保存
fid = fopen(filePath,'w');
fwrite(fid,tmpChar);
fclose(fid);
ひとつだけご注意.上のコードを使うと,MATLABのエディターが「'native2unicode'と'fread'を使用する代わりに、'fopen'の文字エンコーディングスキームを指定してください。」という警告をだします.ですが,「ああそうですか」と言う通りにするとうまくいかないんですよ・・・.どなたか解決されたらご一報いただければありがたいです.
環境
環境・使用プログラム
OS: Windows 10 (64bit)
MeCab: Windows用バイナリパッケージ(mecab-0.996.exe)でインストールしたもの.
MATLAB R2020a
Text Analytics Toolbox
前準備
前記事で書いた前準備,
- 新しいシステム辞書を置くフォルダの作成
- MeCabのインストール
- mecab-ipadic-NElogdのダウンロードと辞書ファイルの解凍
までは,済ませておいてください.では,いざスクリプトへ.
スクリプト
最初に,新辞書フォルダ,NEologdの辞書を置くフォルダ,MeCabがインストールされているフォルダ等を設定します.
newDicDir = 'C:\Temp\newDic'; % 新しく作る辞書のフォルダ
neologdCSVDir = 'C:\Temp\neologd'; % NEologdの辞書ファイルフォルダ
mecabDir = 'C:\Program Files (x86)\Mecab'; % MeCabのインストールフォルダ
mecabDicDir = fullfile(mecabDir,'dic','ipadic'); % MeCabデフォルト辞書のフォルダ
mecabIndexExe = fullfile(mecabDir,'bin','mecab-dict-index.exe'); % 辞書作成プログラム
MeCabのデフォルト辞書(*.csv)は結構数があるので,手入力せずに自動的に取得します.そして,取得したファイル名(文字列配列)に,unk.def
を付け足して,コード変換を行うファイル名のリストを作ります.
tmp = dir(fullfile(mecabDicDir,'*.csv'));
mecabCSVList = string({tmp.name}');
mecabCodeConv = [mecabCSVList; "unk.def"]; % 文字コード変換をするファイルのリスト
上のstring({tmp.name}')
,さりげなく書いてますが「構造体配列のフィールドを一気にセル配列に代入して転置,文字列配列に変換 」というちょっとした小技だったりします.
NEologdのファイルについても同様にファイル名を取得します.そして,ユーザー辞書名(mecab-userで始まるもの)とそうでないものをそれぞれ別々の文字列配列に代入します.
tmp = dir(fullfile(neologdCSVDir,'*.csv'));
neologdCSVList = string({tmp.name}');
isUserDic = startsWith(neologdCSVList,"mecab-user"); %ユーザー辞書かどうかを調べる論理配列
neologdUsrDics = neologdCSVList( isUserDic); % ユーザー辞書名(実は要素は一つだけ)
neologdSysDics = neologdCSVList(~isUserDic); % その他の辞書ファイル名
MeCabの辞書を全て新辞書フォルダにコピーして,コード変換対象ファイルを順次コード変換します
system(sprintf('copy "%s" "%s"',fullfile(mecabDicDir,'*.*'),newDicDir));
% MeCabの辞書のコード変換
for kk = 1:length(mecabCodeConv)
filePath = fullfile(newDicDir, mecabCodeConv(kk));
fid = fopen(filePath,'r');
tmpChar = fread(fid);
fclose(fid);
tmpChar = unicode2native(native2unicode(tmpChar,'Shift-JIS'),'UTF-8');
fid = fopen(filePath,'w');
fwrite(fid,tmpChar);
fclose(fid);
end
NEologdのシステム辞書を新辞書フォルダにコピーして,
for kk = 1:length(neologdSysDics)
system(sprintf('copy "%s" "%s"', fullfile(neologdCSVDir,neologdSysDics(kk)),newDicDir));
end
辞書をビルドします.
cd(newDicDir);
system(sprintf('"%s" -f UTF-8 -t UTF-8',mecabIndexExe));
これで,NEologdのシステム辞書の出来上がりです.
まとまってるコードはこちら
% mecab-ipadic-neologd 辞書システム構築
newDicDir = 'C:\Temp\newDic';
neologdCSVDir = 'C:\Temp\neologd';
mecabDir = 'C:\Program Files (x86)\Mecab';
mecabDicDir = fullfile(mecabDir,'dic','ipadic');
mecabIndexExe = fullfile(mecabDir,'bin','mecab-dict-index.exe');
% MeCab 辞書ファイル名の取得
tmp = dir(fullfile(mecabDicDir,'*.csv'));
mecabCSVList = string({tmp.name}');
mecabCodeConv = [mecabCSVList; "unk.def"]; % 文字コード変換をするファイルのリスト
% NEologd 辞書ファイル名の取得
tmp = dir(fullfile(neologdCSVDir,'*.csv'));
neologdCSVList = string({tmp.name}'); % NEologd辞書ファイルのリスト
isUserDic = startsWith(neologdCSVList,"mecab-user"); % ユーザー辞書かどうかを示す論理配列
neologdUsrDics = neologdCSVList( isUserDic); % ユーザー辞書ファイル名
neologdSysDics = neologdCSVList(~isUserDic); % その他の辞書ファイル名
% MeCabの辞書を新辞書フォルダにコピー
system(sprintf('copy "%s" "%s"',fullfile(mecabDicDir,'*.*'),newDicDir));
% MeCabの辞書のコード変換
for kk = 1:length(mecabCodeConv)
filePath = fullfile(newDicDir, mecabCodeConv(kk));
fid = fopen(filePath,'r');
tmpChar = fread(fid);
fclose(fid);
tmpChar = unicode2native(native2unicode(tmpChar,'Shift-JIS'),'UTF-8');
fid = fopen(filePath,'w');
fwrite(fid,tmpChar);
fclose(fid);
end
% NEologdのシステム辞書を新辞書フォルダにコピー
for kk = 1:length(neologdSysDics)
system(sprintf('copy "%s" "%s"', fullfile(neologdCSVDir,neologdSysDics(kk)),newDicDir));
end
% 辞書をビルド
cd(newDicDir);
system(sprintf('"%s" -f UTF-8 -t UTF-8',mecabIndexExe));