アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

検索にマッチした行を削除するマクロ

サクラエディタで、検索にヒットしたワードを含む行を丸ごと削除したいということがあり、
その数が膨大だったのでサクッとマクロを組んだのをメモ。

結果としてはVBSで書きました。

Dim x
Do While True
    ' 次を検索
    ' (戻り値は使用しないが、変数に入れないとエラーになる…)
    ' 第1引数は検索文字列(空なら現在の設定)
    ' 第2引数はオプション(後述)
    x = Editor.SearchNext("", 38)

    ' 選択範囲が存在する場合は行ごと削除する
    If Editor.GetSelectedString() <> "" Then
        ' 選択を解除するための動作
        Editor.Right()
        Editor.Left()
        ' 行削除
        Editor.DeleteLine()
    Else
        Exit Do
    End If
Loop

通常の検索やこのへんのマクロ( 指定の文字列と同じものをすべて強調表示するマクロ - アナログCPU:5108843109 )と併用する前提。
検索後にこれを実行すれば、対象行がごっそり消えます。
数万行あるようなテキストだと数分かかりました。人力より全然良いけど。

解説

「検索する→ヒットした文字列を含む行をまるごと削除する」
の流れを繰り返しているだけです。
ヒットした文字列は選択状態になるため、選択範囲に何もない場合は繰り返しを終了します。

Dim x
Do While True
    ...
Loop

ただの変数宣言とwhileループです。
以下はその中身。

Editor.SearchNext("", 38)
If Editor.GetSelectedString() <> "" Then
    ...
Else
    Exit Do
End If

SearchNext関数は、通常の検索で「下検索」ボタンを押したときと同じ動作をします。
第1引数は検索する文字列で、空文字列を指定すると、現在の検索対象が採用されます。
第2引数は検索用のボックスにあるものと同じオプションです。

オプションの決め方はちょっとややこしく、
2進数の「000000」に対し、(オプション番号)桁目を1にして、
それを10進数にしたものを設定します。

もうちょっと具体的な例にすると、まず、以下からオンにするものを選びます。

  • 0 単語単位で探す
  • 1 英大文字と小文字を区別する
  • 2 正規表現
  • 3 見つからないときにメッセージを表示
  • 4 検索ダイアログを自動的に閉じる
  • 5 先頭(末尾)から再検索する

例えば「英大文字と小文字を区別する」「先頭(末尾)から再検索する」をオンにする場合、
1桁目と5桁目が1である2進数を用意します。
この桁数は右から数えるので、「100010」となります。
これを10進数に変換すると34になるので、これを第2引数にセットします。

今回は正規表現にしたかったので「100110」、10進数で「38」をセットしています。

参考:
S_SearchNext


その下はただのif文。
GetSelectedString関数で選択範囲の文字列を取得できるので、
その中身が空でない場合のみ処理を行います。

Elseブロックの「Exit Do」は他言語で「break」等に相当するものです。
要するにWhileブロックから抜けます。

以下はIfブロックの中身について。

Editor.Right()
Editor.Left()
Editor.DeleteLine()

カーソルを右に動かし、左に動かし、カーソルが存在する行をまるごと削除する。
範囲選択状態だとDeleteLine関数が動作しないのでこのような挙動となっています。
(もっとスマートなやり方はあるのだろうか…)

サクラエディタのキーマクロでは?

なんとif文が使えないらしく、今回は上記のようにVBSで実装しました。

S_SearchNext('', 38);
S_Right();
S_Left();
S_DeleteLine();

一応、こんな感じであれば「次を検索して削除」を1回だけやってくれるマクロになります。
が、検索結果が見つからなかった場合も1行削除されてしまうという…。