MATLAB Live ScriptからMarkdownへのデータの書き出し
Live Script でデータ解析をすれば、コードとその計算結果が全部一箇所に保存できるので、これだけで十分、と思っていましたが、実際にその計算結果を利用して論文に記載しようと思うと、長大な Live Script そのままでは、コードに埋もれてしまって、肝心の数字を見つけるのがかなり鬱陶しいということを自覚しました。
数字を見つけて、Wordにコピーするだけで数日かかってしまった上、後から問題が見つかって計算をやり直したので、もうこの作業を繰り返すわけにはいかんと結論したのでした。
そこで、結局、Live Script の中で、重要な箇所について、Live Script の出力に数字を吐き出しながら、同時に、テキストファイルに markdown を書き出して、要点だけが見られるようにまとめることにしました。
私の解
正直あまりエレガントとは言えませんが、落ち着いたのはこのような形です。
もともと Live Scriptで、このような形で、セミコロンを省くことで計算結果を吐き出せていたとします。
length(A)
table(B,C,D,...
'VariableNames',{'John','Ben','Tom'})
それをこのように書き換えます。
fid = fopen('foo.md','w','n','UTF-8');
fp = @(x,y) fprintfcodemd(fid,x,y);
fprintf(fid,'# Length of A');
s = 'length(A)';
fp(s,evalc(s));
fprintf(fid,'# Data of 3 people');
s = [...
"table(B,C,D,...";...
"'VariableNames',{'John','Ben','Tom'})";...
];
fp(s,evalc(regexprep([s{:}],'\.{3}','')));
fclose(fid);
解説
fid = fopen('foo.md','w','n','UTF-8');
fid = fopen('foo.md','w','n','UTF-8');
'w'
オプションで、'foo.md'
という名前の markdownファイルを新たに作ります。既に同じ名前のファイルが存在する場合は上書きします。
'n','UTF-8'
によって、Unicodeに文字コード指定します。evalc
出力には頻繁に×
(掛け算記号)が用いており、Unicodeに指定しないとWindowsでは文字化けが起こります。
fprintf(fid,'# Length of A\n');
これは上で作ったファイルに、markdownで見出し(#
はH1
)を書き込んでいます。
fp = @(x,y) fprintfcodemd(fid,x,y);
これは、鬱陶しいので表記を短くするための行です。
@
で無名関数(anonymous function)を作り、fp
という短い名前で呼べるようにします。
fp(s,evalc(s));
関数fprintfcodemd
は、markdownのコードブロック(```で挟まれた部分)に、プロンプトの記号
>>
と、文字列s
そのものを書き込み、その下にevalc(s)
の出力、つまりs
に書かれたコードに対するコマンドウィンドウの出力を書き込みます。このとき、実はevalc
の出力は太字指定などの HTML タグを含んでしまっているので、関数fprintfcodemd
の内部でこれを除去しています。
evalc
の実行時に、s
に登場する変数全てにアクセスする必要があるため、このevalc
は関数fprintfcodemd
に内蔵させることができません。
markdownの出力はこのようなイメージです。
# Length of A
```
>> length(A)
ans =
19
```
s = {'table(B,C,D,...';...
'''VariableNames'',{''John'',''Ben'',''Tom''})'};
二つ目の例は、s
が複数行にまたがっているのが厄介です。一行に無理やり突っ込んでもいいですが、非常に長くなってしまう場合もあるのでいつも良いとは限りません。
ここでは、仕方なく、コードを文字列のセル配列 cell array of strings としてs
に格納しています。その時に、'
を繰り返してエスケープせざるを得ないので可読性がとても悪化しています。
s = ["table(B,C,D,...";...
"'VariableNames',{'John','Ben','Tom'})"];
このように、代案として、最近新しく加わった string型を利用して単引用符'
の代わりに、複引用符"
を使うと、あまり元のコードを乱さずに済みます。遥かに可読性が高いですし、書くのも楽ですね。
fp(s,evalc(regexprep([s{:}],'\.{3}','')))
s
をそのままevalc
に渡すとエラーが出るので、char
型に変換する必要があります。ここでは、regexprep([s{:}],'\.{3}','')
によって、一行のコマンドに直しています。
使用した関数 fprintfcodemd
function fprintfcodemd(fid,expr,evalcout)
p = inputParser;
p.addRequired('fid',@(x) isscalar(x));
p.addRequired('expr',@(x) ischar(x) || iscellstr(x) || isstring(x) );
p.addRequired('evalcout',@(x) ischar(x));
p.parse(fid,expr,evalcout);
if ischar(expr)
expr = {regexprep(expr,';$','')};
elseif isstring(expr)
expr = cellstr(expr);
end
% print to file fid
fprintf(fid,'\n```\n>> ');
fprintf(fid,'%s\n',expr{:});
evalcout_ = regexprep(evalcout,'<[/\w][^>]*[\w"]>',''); % get rid of HTML tags
fprintf(fid,evalcout_); %
fprintf(fid,'```\n\n');
% print to Command Window
fprintf('\n>> ');
fprintf('%s\n',expr{:});
%fprintf(['>> ',expr,'\n']);
fprintf(evalcout);
fprintf('\n');
end
function fprintfcodemd(fid,expr,evalcout)
p = inputParser;
p.addRequired('fid',@(x) isscalar(x));
p.addRequired('expr',@(x) ischar(x) || iscellstr(x) || isstring(x) );
p.addRequired('evalcout',@(x) ischar(x));
p.parse(fid,expr,evalcout);
if ischar(expr)
expr = {regexprep(expr,';$','')};
elseif isstring(expr)
expr = cellstr(expr);
end
% print to file fid
fprintf(fid,'\n```\n>> ');
fprintf(fid,'%s\n',expr{:});
evalcout_ = regexprep(evalcout,'<[/\w][^>]*[\w"]>',''); % get rid of HTML tags
fprintf(fid,evalcout_); %
fprintf(fid,'```\n\n');
% print to Command Window
fprintf('\n>> ');
fprintf('%s\n',expr{:});
%fprintf(['>> ',expr,'\n']);
fprintf(evalcout);
fprintf('\n');
end
Author And Source
この問題について(MATLAB Live ScriptからMarkdownへのデータの書き出し), 我々は、より多くの情報をここで見つけました https://qiita.com/kouichi-c-nakamura/items/fb7c056b3b4867ac6687著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .