vim-users.jp

Hack #113: grex – 特定パターンにマッチする行をまとめて取り扱う

Posted at 2009/12/31
このエントリーをはてなブックマークに追加

問題

Vimで大量のデータを取り扱う場合、 特にCSVなどの1レコード1行の形式のデータを取り扱うとき、 特定の条件にマッチする行を抽出するなど、 まとめて編集したいことがしばしばあります。

例えばバッファの内容が以下のようになっていたとします:

Name      Creator            First release Cost License          Open source
Diakonos  Pistos             2004          Free MIT              Yes
GNU Emacs Richard Stallman   1984          Free GPL              Yes
JED       John E. Davis      1992          Free GPL              Yes
Metapad   Alexander Davidson 1999          Free GPL              Yes
Notepad   Microsoft          1985          -    Proprietary      No
RText     Fifesoft           2003          Free GPL              Yes
SciTE     Neil Hodgson       1999          Free HPND             Yes
Vim       Bram Moolenaar     1991          Free GPL - compatible Yes
Yi        Don Stewart        2005          Free GPL              Yes

この中から 「19XX年にリリースされたエディタ(に対応する行)を削除する」 としましょう。 これは:globalを利用して行うことができます (:g/\<19\d\d>/d)。

では 「19XX年にリリースされたエディタ(に対応する行)をヤンクする」 としたらどうでしょうか。 すぐに思いつくのは:g/\<19\d\d>/yですが、 これはマッチする行で毎回ヤンクを行うため、 レジスタに残るのは最後にマッチした行のテキストだけになります。 つまり、ヤンクしたいテキストは以下の通りなのですが、

GNU Emacs Richard Stallman   1984          Free GPL              Yes
JED       John E. Davis      1992          Free GPL              Yes
Metapad   Alexander Davidson 1999          Free GPL              Yes
Notepad   Microsoft          1985          -    Proprietary      No
SciTE     Neil Hodgson       1999          Free HPND             Yes
Vim       Bram Moolenaar     1991          Free GPL - compatible Yes

実際にヤンクされるのは以下の1行だけになります。

Vim       Bram Moolenaar     1991          Free GPL - compatible Yes

この観点で考えると、最初の「削除」についても同様のことが言えます。 つまり、削除されたテキストを別の箇所にペーストした場合、 ペーストされるのは最後にマッチした行のテキストだけになります。

上記のように、特定パターンにマッチする行をまとめて削除/ヤンクして ペーストするにはどうすればよいでしょうか。

解決方法

ベタな解決方法としては、 削除/ヤンクされるテキストをレジスタに上書きするのではなく、 レジスタに追加するようにします。 これには"A-"Zなどの大文字のレジスタを使います。

例えば:g/{pattern}/y Aとすると、 "aレジスタにマッチする各行のテキストが追記されるので、 "ap (操作直後であればpだけ)で 各行のテキストを一度にペーストできます。

ところが既に"aに何か別のテキストが入っていた場合、 それに対してテキストが追加されていくため、 実際には:let @a = ''などとして 操作前にレジスタの内容を空にする必要があります。 これは結構面倒です。

幸いなことに、上記のような操作パターンをまとめたコマンドを提供する grex というプラグインがありますので、これを使うと簡単に行うことができます。

例えば特定パターンにマッチする行をまとめて削除する場合、 /\<19\d\d>などとしてマッチするかどうかを確認した後、 :Gredで行うことができます。 ヤンクであれば:Greyで行うことができます。

なお、各コマンドは:g/{pattern}/[cmd]と 同様の形式では実行できません。 これは通常の操作では 検索パターンを含むコマンドを一度に入力して実行することはなく、 ('incsearch'および'hlsearch'を有効にした上で)/{pattern}により 期待通りの検索パターンができたかどうかをインタラクティブに確認してから 実際のコマンドを入力・実行することがほとんどだからです。

参考資料

kana

もどる
blog comments powered by Disqus