|
でるもんた・いいじま@秀丸歴20年の年寄り、です。
> マクロを作成しました。
かなりの力作ですね。努力の跡がハッキリと見えます。
ただ、これを言ってしまうのはちょっと心苦しいのですが、
「C言語なら確かにこの方針で書いてもいいんだけど、
秀丸マクロとかPerlとか、あるいは他の最近の言語なら、
もっと格段に短くて読みやすくて、動作も速いコードが
書けるのでは?」
と思ってしまいました。なのでゴメンナサイ、せっかく投稿して
いただいたマクロはほとんど読まずに代案を提案させていただきます。
> 途中までは、うまく動作しているようですが、
> ループの終了条件が間違っているようで、最終的には、
> 意図したテキストになりません。マクロも終了しません。
コードをざっと見る限り、
「既にファイルの末尾に来ていて、code==eofになっているのに、
while ( code!=0x0D ) { ... } の無限ループに落ち込んでいる」
というのが原因だと思います。
#「データ終わり」を示す文字コードが EOF、\0、\n の3つある、
#ってのは、C言語とかではありがちな罠ですね。
☆ ☆ ☆
というわけで、要求仕様だけから書き起こしてみました。
まずは、「データ2つで1行」に固定のバージョン。
//- - - - - - - - - - - - - - - - キリトリセン - - - - - - - - - - - - - - -
setcompatiblemode 0x20000;
// Step 1: 空行なしで続いている複数行を、1行にまとめてしまう。
begingroupundo;
replaceallfast @"(?<!\n)\n(?!\n)", "", regular;
// replaceallfast @"([^\n])\n([^\n])", @"\1\2", regular; //こう書いてもよい
// 上記の置換ではファイルの最後の改行を取り除いてしまうので、付け直す。
gofileend;
insert "\n";
endgroupundo;
// Step 2: 改行区切りからタブ区切りへ一気に置換
// ※maxlinesの値は足りなければ増やしてください。
$reFROM = @"(?#maxlines:10)\n*([^\n]+)\n+([^\n]+)\n";
$reTO = @"\1\t\2\n";
begingroupundo;
replaceallfast $reFROM, $reTO, regular;
endgroupundo;
endmacro;
//- - - - - - - - - - - - - - - - キリトリセン - - - - - - - - - - - - - - -
で、上記のコードでは、$reFROM、$reTO という変数に正規表現を
代入していますが、この正規表現自体をマクロで編集することで、
2列ではなく任意の列数で同様のことができます。
そうすると、最終的にこんなコードになりました。
//- - - - - - - - - - - - - - - - キリトリセン - - - - - - - - - - - - - - -
#MAXNUM_PARENS = 15; // V8.58時点での仕様
// Step 0: 初期設定
if (version < 858 )
{
message "このマクロには、秀丸エディタV8.58以上が必要です。";
endmacro;
}
setcompatiblemode 0x20000;
// Step 1: 列数を入力してもらう
again:
#n = val( input("いくつのデータを1行にまとめますか?","2") );
if ( !result ) endmacro;
if ( #n<2 || #n>#MAXNUM_PARENS )
{
message "指定できるのは2から" + str(#MAXNUM_PARENS) + "までです。";
goto again;
}
// Step 2: 空行なしで続いている複数行を、1行にまとめてしまう。
begingroupundo;
replaceallfast @"(?<!\n)\n(?!\n)", "", regular;
// replaceallfast @"([^\n])\n([^\n])", @"\1\2", regular; //こう書いてもよい
// 上記の置換ではファイルの最後の改行を取り除いてしまうので、付け直す。
gofileend;
insert "\n";
endgroupundo;
// Step 3: 改行区切りからタブ区切りへ一気に置換するため、正規表現を生成
// ※maxlinesの値は足りなければ増やしてください
$reFROM = @"(?#maxlines:10)\n*";
#i = 1;
while ( #i < #n )
{
$reFROM = $reFROM + @"([^\n]+)\n+";
$reTO = $reTO + sprintf(@"\g{%d}\t", #i);
#i = #i+1;
}
$reFROM = $reFROM + @"([^\n]+)\n";
$reTO = $reTO + sprintf(@"\g{%d}\n", #n);
message sprintf("実行内容:\nFROM=「%s」\nTO=「%s」", $reFROM, $reTO);
// Step 4: 一気に置換!
begingroupundo;
replaceallfast $reFROM, $reTO, regular;
endgroupundo;
endmacro;
//- - - - - - - - - - - - - - - - キリトリセン - - - - - - - - - - - - - - -
正規表現を使いこなせるようになると、1文字単位の処理では面倒すぎる
処理が簡単にできてしまって、しかもスピードも格段に速くなります。
(正規表現どおりに検索・置換する処理は、C言語で既に徹底的に
チューニングされています。したがって、同じ処理を下手に
スクラッチから書くよりも「早い」上に「速い」のです。)
kukeさんもぜひ、正規表現を使いこなせるようになってください。
|
|