キーマクロによる置換についてNo.09817
tack さん 22/04/15 22:29
 
お世話になっております。

以下のような文字列がある場合、キーマクロにて置換ができるのかを考えているので
すが、可能であれば教えてください。

"menu":[
りんご,
梨,
みかん,
りんご,
ぶどう,
梨,
梨,]
"price":[
200,
300,
250,
400,
350,
300,
350,]
"remarks":[
null,
null,
null,
null,
null,
null,
null,]


上記のリストを下記のように配置したいのです。

"menu":[
りんご,200,null,
梨,300,null,
みかん,250,null,
りんご,400,null,
ぶどう,350,null,
梨,300,null,
梨,350,null,

各々のグループにある文字列の数は等しいものと考えていただいて結構です。
キーマクロではなくマクロを使うしかないのでしょうか?自分がマクロに疎いもので、
マクロを使わずできればと思っているのですが。

[ ]
RE:09817 キーマクロによる置換についてNo.09818
こみやんま さん 22/04/15 23:33
 
こ、これをキーマクロで...

元のデータに最後改行がちゃんと入っているものとします。
===============================================
CTRL+HOME
検索で"menu" でF3
HOME
下キー
SHIFT+下キー
CTRL+X
CTRL+END
CTRL+V
BACKキー

CTRL+HOME
検索で"price" でF3
HOME
下キー
SHIFT+下キー
CTRL+X
CTRL+END
CTRL+V
BACKキー

CTRL+HOME
検索で"remarks" でF3
HOME
下キー
SHIFT+下キー
CTRL+X
CTRL+END
CTRL+V
===============================================
ここまでをキーマクロとして記録
===============================================

これでキーを再生すれば、3つ1組ずつ下へと加えられていくのではないかと。
(キーマクロでやらないほうがいいんじゃないかなーと個人的には思いますが)

[ ]
RE:09818 キーマクロによる置換についてNo.09819
こみやんま さん 22/04/15 23:38
 
最後の組だけちょっと ] が入っちゃいますが、
キーマクロだからそのくらいいは最後手作業で除去していいのではないかと思います。

[ ]
RE:09819 キーマクロによる置換についてNo.09820
tack さん 22/04/16 16:54
 
こみやんま様
ご返信ありがとうございます、確かに教えていただいた方法で可能でしたが、仰る通
りデータ数が増えてくるとキーマクロで行うには向かないと感じました。
やはりマクロにて行う方が正確かつ分かりやすいということでしょうか。

[ ]
RE:09820 キーマクロによる置換についてNo.09821
こみやんま さん 22/04/17 18:52
 
キーマクロは、通常のマクロとして保存可能なので、上記キーマクロは
=== key_macro.mac として保存 ==================
setcompatiblemode 0x0F;

gofiletop;
searchdown "\"menu\"" , casesense, hilight;
if( ! result )  beep;
golinetop;
down;
beginsel;
down;
cut;
gofileend;
paste;
backspace;

gofiletop;
searchdown "\"price\"" , casesense, hilight;
if( ! result )  beep;
golinetop;
down;
beginsel;
down;
cut;
gofileend;
paste;
backspace;
gofiletop;

searchdown "\"remarks\"" , casesense, hilight;
if( ! result )  beep;
golinetop;
down;
beginsel;
down;
cut;
gofileend;
paste;
=====================

みたいになることでしょう。

これを利用しにかかるとすれば、

============= reposition_1.mac ==============
setcompatiblemode 0x0F;

begingroupundo;
disabledraw;

gofileend;
insertreturn;
replaceallfast @"^\n" , @"" , regular, nohilight;
replaceallfast @",\]\n" , @",\n\]\n" , regular, nohilight;
if( ! result )  beep;
enabledraw;
endgroupundo;

gofiletop;

searchdown @"^\]\n" , regular, hilight;

// 1つの構造体の行
#one_struct_lines_number = lineno;

// 全ての構造体の行
#all_struct_lines_number = linecount2;

// 構造体の数
#struct_count = #all_struct_lines_number / #one_struct_lines_number;

begingroupundo;
disabledraw;

//  1つの構造体の開始の{ と 1つの構造体endの}の行を引く。残りがデータ数
while(#try_count < #one_struct_lines_number-2) {
    execmacro currentmacrodirectory + @"\key_macro.mac";
    #try_count = #try_count + 1;
}

enabledraw;
endgroupundo;
====================================================

みたいな形になるかと、ただしキーマクロが入ってしまっているので遅いでしょう。

とはいえ、jsonもどきのデータ数が千件くらいならあまり問題ないかと思います。


一段とスピードを上げるなら、
============= reposition_2.mac ==============
setcompatiblemode 0x0F;

begingroupundo;
disabledraw;

// 最後の行に改行足す
gofileend;
insertreturn;

gofiletop;
replaceallfast @"^\n" , @"" , regular, nohilight;
replaceallfast @",\]\n" , @",\n\]\n" , regular, nohilight;
if( ! result )  beep;
enabledraw;
endgroupundo;

gofiletop;

searchdown @"^\]\n" , regular, hilight;

// 1つの構造体の行
#one_struct_lines_number = lineno;

// 全ての構造体の行
#all_struct_lines_number = linecount2;

// 構造体の数
#struct_count = #all_struct_lines_number / #one_struct_lines_number;

// 最後の行に足す
gofileend;
insertreturn;

#struct_index = 0;
#line_index = 2;

$all_string_buffer = "";

if (#struct_count > 1) {

    // 先頭の構造体のラインindex
    while(#line_index < #one_struct_lines_number) {

        $string_buffer = "";

        // 構造体自体の○番目
        #struct_index = 0;
        while(#struct_index < #struct_count) {

            // 対象の行番号
            #target_line = #line_index + #struct_index * #one_struct_lines_n
umber;

            // テキスト取得
            $text = gettext2(0, #target_line, linelen2[#target_line-1], #tar
get_line, 0, 1);

            // バッファーに足しこみ
            $string_buffer = $string_buffer + $text;

            #struct_index = #struct_index + 1;
        }

        // これが1ライン
        $string_buffer = $string_buffer + "\n";

        // 全バッファーに足しこみ
        $all_string_buffer = $all_string_buffer + $string_buffer;

        #line_index = #line_index + 1;
    }

    insert $all_string_buffer;
}
====================================================

みたいな形ですかねぇ。
元のデータが大きいと
$all_string_buffer のバッファーが足りないかもしれないので、
秀丸の「パフォーマンスと上限の詳細」の「マクロの変数の上限」を増やさないとだ
めかもしれないですねぇ。

元データ数が1万件くらいまでならあまりストレスなくいくのではないでしょうか。

いずれにしても2つとも綱渡りで頼りなく、
私なら「1度ここで変換したら終わり」ならこんな形で変換してしまうと思いますが、
「毎度やる変換パイプライン」にこの工程を入れるなら
危なすぎるので採用しません。
元データをJsonなりにして、そこから変換しますかねぇ。

[ ]
RE:09821 キーマクロによる置換についてNo.09822
tack さん 22/04/17 19:11
 
こみやんま様
確かに、自分が教えていただいた方法で記録したキーマクロもその通りの記述でした。

そのキーマクロを別のマクロで参照して、データ数分だけ実行させるということで理
解は間違っていないでしょうか?

また、確かにjson形式にすることができるテキストファイルでありますが、jsonを変
換するのが
json整形しか出てこず、そちらの理解が全然進んでおりません。
ここで話す話題ではありませんが、別の方法があるものなのでしょうか?

[ ]
RE:09822 キーマクロによる置換についてNo.09823
こみやんま さん 22/04/17 23:31
 
>こみやんま様
>確かに、自分が教えていただいた方法で記録したキーマクロもその通りの記述でした。
>
>そのキーマクロを別のマクロで参照して、データ数分だけ実行させるということで
>理解は間違っていないでしょうか?

そのとおりです。


json(=JavaScript Object Notation)はjavascriptのオブジェクトそのもの、データ
構造そのものなので、ツールとか介しいてもいいですが、
やりたいことが明らかなのに使い方がわからない感じになりやすいので、
javascript系を用いて自分で変形するのが一番早いと思いますけどね。

-------------- test.json -------------------------
{
    "menu": [
        "りんご",
        "梨",
        "みかん",
        "りんご",
        "ぶどう",
        "梨",
        "梨"
    ],
    "price": [
        200,
        300,
        250,
        400,
        350,
        300,
        350
    ],
    "remarks": [
        null,
        null,
        null,
        null,
        null,
        null,
        null
    ]
}

-------------- node.js を 使って変形 の例 test.jsonをtest_dst.jsonへ -------
-------
const fs = require('fs');

// test.jsonの内容を読み込み
const json_string = fs.readFileSync('./test.json', 'utf8');

// パース
const json_obj = JSON.parse(json_string);

// jsonのオブジェクト別形態用
let json_obj_dst = {}

// 結果の文字列用
let json_string_buffer = "";

// 元データの3つの系統からix番目を1つずつもってきて1つの塊にまとめる。
for(ix=0; ix < json_obj["menu"].length; ix++) {
    // 1行のデータ。配列にしとく。JSON.stringify の表示が芳しい形を採用
    json_obj_dst[ix] = [json_obj["menu"][ix], json_obj["price"][ix], json_ob
j["remarks"][ix] ];

    // ,や改行入れて、それっぽく
    json_string_buffer += JSON.stringify(json_obj_dst[ix]) + ",\n";
}

// 全体をファイルに出力
fs.writeFileSync("test_dst.json", json_string_buffer);
------------------------------------------------------------------------


-------------- hmV8の例 (test.jsonを開いているとして変換) --------------
// https://秀丸マクロ.net/?page=nobu_tool_hm_ecmascript

#DLL = loaddll(hidemarudir + @"\hmV8.dll");
#_ = dllfuncw(#DLL, "DoString", R"JS(

// 現在開いているファイルのテキストの内容(jsonと仮定)を読み込み
var json_string = hm.Edit.TotalText;

// パース
var json_obj = JSON.parse(json_string);

// jsonのオブジェクト別形態用
let json_obj_dst = {}

// 結果の文字列用
let json_string_buffer = "";

// 元データの3つの系統からix番目を1つずつもってきて1つの塊にまとめる。
for(ix=0; ix < json_obj["menu"].length; ix++) {
    // 1行のデータ。配列にしとく。JSON.stringify の表示が芳しい形を採用
    json_obj_dst[ix] = [json_obj["menu"][ix], json_obj["price"][ix], json_ob
j["remarks"][ix] ];

    // ,や改行入れて、それっぽく
    json_string_buffer += JSON.stringify(json_obj_dst[ix]) + ",\n";
}

// 全体を1つの文字列として秀丸マクロ変数へ
hm.Macro.Var["$json_string_buffer"] = json_string_buffer;

)JS"
);

freedll(#DLL);

newfile;
insert $json_string_buffer;
------------------------------------------------------------------------



[ ]
RE:09823 キーマクロによる置換についてNo.09824
こみやんま さん 22/04/18 00:29
 
node や hmV8 が導入しがたい場合は、PowerShellがいいかもしれませんね。
PowerShellの実行が有効でない場合には適当にググって有効化するとして、

====================test.ps1 で保存===========================
$jsonContent = (Get-Content -Encoding UTF8 .\"test.json" | ConvertFrom-Json);
$len = $jsonContent.menu.length
for ($ix=0; $ix -lt $len; $ix++){
    $data = @( $jsonContent.menu[$ix], $jsonContent.price[$ix], $jsonContent.
remarks[$ix] );
    Write-Output((ConvertTo-Json -Compress $data));
}
============================================================

みたいな形で、先述の.jsonファイルは加工できると思います。

これをPowerShellコンソール上で、
============================================================
./test.ps1 > test_dst.json などとすれば変換できるでしょう。
============================================================

普段からあまり言語らしい言語は利用していない、といった場合は、
上記PowerShellによる変換がお手軽かもしれませんね。

[ ]
RE:09817 キーマクロによる置換についてNo.09828
秀丸担当 さん 22/04/18 15:49
 
マクロを使わず簡便にキー操作の記録と再生でやる方法ということで、一般的な例と
してですが、参考までに書いておきます。

1つの考え方として、バッファに溜めて、それを吐き出すという方法が幾つかありま
す。

簡単には、最初は「コピー」して、2回目、3回目は「追加コピー」して、それを貼
り付けします。(または切り抜き/追加切り抜き)
例えば「りんご」から始まって、8行下に移動、「200」をコピー、8行下に移動、
「null」を追加コピー、「りんご」の位置に戻って貼り付けといった感じです。
(カーソル位置の詳しい移動は省いています)

似た手法として、クリップボード履歴がONのとき、「コピー」を繰り返して、「貼り
付け+履歴戻し」コマンドを使う方法もあります。この場合は、最後にコピーしたも
のから、遡って貼り付けしていきます。
例えば、「null」をコピー、「200」をコピー、「りんご」の位置で、「貼り付け+履
歴戻し」を2回します。

クリップボードを使わない同様の方法として、「削除」を繰り返し、「削除内容復
元」で挿入する方法があります。
例えば、「null」を削除、「200」を削除、「りんご」の位置で、「削除内容復元」
を2回します。

7個分操作を間違えずに記録するのは大変なので、例えば1つの要素分だけ記録して、
「キー操作の保存...」してマクロファイルにしておきます。
そして保存したマクロファイルを7回実行する操作を、もう1つのまとまりとして記
録します。

----

まったく別の考え方の順番入れ替えの手段として、行頭に番号を手動入力して、範囲
選択して、[編集]→[変換]→[ソート]でソートして、行頭の番号を消すというのも簡
単だと思います。
例えば、以下のように手動で番号を入れて、範囲選択し、ソートして、手動で番号を
消します。

01:りんご
03:梨
02:みかん
04:ぶどう

番号入れるのが面倒ですが、1度記録さえすれば、どのようなルールの順番でも簡単
に対応できると思います。

----

正規表現を使って複数行の検索をする場合、簡単な方法として、検索ダイアログの入
力欄の右側の「>」をクリックして、「複数行」をONにしておくといいです。
内容不定の場所を.*としておけば、あまり深いことを考えずに検索できます。

"menu":.*
.*
.*
.*
.*
.*
.*
.*
"price".*
.*

もし試される場合、検索ダイアログの「選択した範囲」が、範囲選択中に自動的にON
になることがあるので注意が必要です。
[その他]→[動作環境]→[検索]→[検索ダイアログ]で「選択した範囲」は常にOFFに
もできます。

----

こういった1まとまりの作業をキー操作の記録/再生をするとして、再生する回数が
たくさんある場合、「キー操作のリピート再生...」コマンドをするといいです。
「キー操作のリピート再生...」コマンドは、通常メニューに無いですが、[その他]
→[メニュー編集...]で、メニューバーのマクロメニュー内に表示できます。

記録内容に検索が含まれる場合、「検索・カーソル移動ができなくなるまで」で実行
すると全自動になり、上記を組み合わせることで、マクロを書かなくてもできると思
います。

[ ]