MATLABでmecab-ipadic-NEologdをシステム辞書として使う：自動化スクリプト

# はじめに
前記事，[MATLABでmecab-ipadic-NEologdをシステム辞書として使う](https://qiita.com/h583/items/626eda59095792a22690)を書いた後で，「辞書のビルドをするのに，特定のファイルをコピーしたり，その一部だけをコード変換したりという手続きが面倒臭いなぁ，MATLABから一発でできないかなぁ」などと思いながらMATLABドキュメントの森を探索しているうちに，何とかなりそうだったのでやってみたら何とかなっちゃいました．

鍵は辞書ファイルのコード変換．下の例では，ファイル```fileToConvet.csv``` を開いてShift-JISからUTF-8へコード変換して，上書き保存してます．これができれば後はスクリプトを普通に書くだけなので，大事な部分はここまで．

```matlab
filePath = 'fileToConvert.csv';

% ファイルの中身を全部読み込んで
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);
```
ひとつだけご注意．上のコードを使うと，MATLABのエディターが「'native2unicode'と'fread'を使用する代わりに、'fopen'の文字エンコーディングスキームを指定してください。」という警告をだします．ですが，「ああそうですか」と言う通りにするとうまくいかないんですよ・・・．どなたか解決されたらご一報いただければありがたいです．

__環境__
環境・使用プログラム
OS: Windows 10 (64bit)
MeCab: Windows用バイナリパッケージ（mecab-0.996.exe）でインストールしたもの．
MATLAB R2020a
Text Analytics Toolbox

# 前準備
[前記事](https://qiita.com/h583/items/626eda59095792a22690)で書いた前準備，

* 新しいシステム辞書を置くフォルダの作成
* MeCabのインストール
* mecab-ipadic-NElogdのダウンロードと辞書ファイルの解凍

までは，済ませておいてください．では，いざスクリプトへ．

# スクリプト
最初に，新辞書フォルダ，NEologdの辞書を置くフォルダ，MeCabがインストールされているフォルダ等を設定します．

```matlab

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```を付け足して，コード変換を行うファイル名のリストを作ります．

```matlab

tmp = dir(fullfile(mecabDicDir,'*.csv'));
mecabCSVList = string({tmp.name}');

mecabCodeConv = [mecabCSVList; "unk.def"];  % 文字コード変換をするファイルのリスト
```
上の```string({tmp.name}')``` ，さりげなく書いてますが「構造体配列のフィールドを一気にセル配列に代入して転置，文字列配列に変換 」というちょっとした小技だったりします．

NEologdのファイルについても同様にファイル名を取得します．そして，ユーザー辞書名（mecab-userで始まるもの）とそうでないものをそれぞれ別々の文字列配列に代入します．

```matlab

tmp = dir(fullfile(neologdCSVDir,'*.csv'));
neologdCSVList = string({tmp.name}');

isUserDic = startsWith(neologdCSVList,"mecab-user"); %ユーザー辞書かどうかを調べる論理配列

neologdUsrDics = neologdCSVList( isUserDic); % ユーザー辞書名（実は要素は一つだけ）
neologdSysDics = neologdCSVList(~isUserDic); % その他の辞書ファイル名
```

MeCabの辞書を全て新辞書フォルダにコピーして，コード変換対象ファイルを順次コード変換します

```matlab

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のシステム辞書を新辞書フォルダにコピーして，

```matlab

for kk = 1:length(neologdSysDics)
  system(sprintf('copy "%s" "%s"', fullfile(neologdCSVDir,neologdSysDics(kk)),newDicDir));
end
```
辞書をビルドします．

```matlab

cd(newDicDir);
system(sprintf('"%s" -f UTF-8 -t UTF-8',mecabIndexExe));
```
これで，NEologdのシステム辞書の出来上がりです．


<details><summary>まとまってるコードはこちら</summary><div>

```matlab
% 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));
```
</div>