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