今風?の言語でよくやるリスト処理とVimの複数行処理って似てるじゃん!
って思ってビルド待ち時間とかに書いてみた記事です
Vimの複数行処理(名前は今付けた)って、すっっっごい便利だし大して難しくないのにあまり知られていない気がする...
ので、ちょっと捉え方を変えて説明できるか試してみるよ
ここで言うリスト処理というのは、よくやる
対象選択(list) -> 条件で絞り込み(filter) -> 変換処理(map)
のことです
filterって?
複数の要素の中から条件
に一致する要素のみを残す処理のこと
Javaだと
Streamで
Stream.of("foo", "bar", "baz").filter(s -> s.startswith("b")).collect(Collectors.toList()) // [bar, baz]
s -> s.startswith("b")
の部分が条件
Pythonだと
内包表記で
[s for s in ["foo", "bar", "baz"] if s.startswith('b')] # ['bar', 'baz']
s.startswith('b')
の部分が条件
じゃあVimだと?
Vimの複数の要素と条件とはなんだろうか
要素は行、条件は検索文字列(正規表現含む)と置き換えて考えるとうまくはまる
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2Fdc910233-f7fd-f311-385c-864c983e0d26.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=5ea9ae0ec699a3f8f574a05b66683e39)
mapって?
複数の要素それぞれに変換処理
を適用する
Javaだと
やはりStreamで
Stream.of("foo", "bar", "baz").map(s -> s + "!").collect(Collectors.toList()) // [foo!, bar!, baz!]
s -> s + "!"
の部分が変換処理
Pythonだと
こちらも内包表記で
[s + '!' for s in ["foo", "bar", "baz"]] # ['foo!', 'bar!', 'baz!']
s + '!'
の部分が変換処理
じゃあVimだと?
Vimで言う変換処理は普段のキーボード操作だ(普段とはnormalモードのこと)
normalモードでA!
とすると行末に移動して!を挿入するので、A!
の部分が変換処理
filterとmapの合わせ技
JavaやPythonだと当然組み合わせて色々出来ちゃうが、Vimでも同じなのだ!
Javaだと
Stream.of("foo", "bar", "baz").filter(s -> s.startswith("b")).map(s -> s + "!").collect(Collectors.toList()) // [bar!, baz!]
Pythonだと
[s + '!' for s in ["foo", "bar", "baz"] if s.startswith('b')] # ['bar!', 'baz!']
で、Vimだと?
:%g/^b/normal A!
...!
見慣れないかもしれないが、なんのことはない!
/
で分けてひとつずつ見てみると
%g
- 対象選択だ
- Javaで言う
Stream.of("foo", "bar", "baz")
にあたる -
%
は全行を意味するVimの記号だ - Visualモードで
:
を押すと'<,'>
となり、反転している行という意味になる - ほかにも
.
や$
という記号もあるが、%
と範囲選択だけ覚えていれば問題はない -
%v
というのもあり、条件に一致しなかった行を対象とする -
grep
とgrep -v
から来ているのかな? - 下の方にサンプルがあるよ
^b
- 条件での絞り込みだ
- Javaで言う
.filter(s -> s.startswith("b"))
にあたる
normal A!
- 変換処理だ
- Javaで言う
.map(s -> s + "!")
にあたる - normalモードで
A!
をストロークしたことにする、という意味になる
だから
つなげて読むと一緒でしょ?
Stream.of("foo", "bar", "baz").filter(s -> s.startswith("b")).map(s -> s + "!")
:%g/^b/normal A!
で、何がうれしいのって? なんでもできるよ!!!
空行を削除したり
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2Ffd974501-0a96-a1ac-d4b9-435e239cf457.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=756cf7fba3f9c8ee47d84cb6ebe966c8)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F0edba398-a9a5-7c08-5aad-e05c96327419.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=91926c639e11acbb50dea445f0f58927)
行末の;
がない行にだけ;
をつけたり
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F4b595bf8-ce41-336e-b5c9-85921f267614.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=aca7d89886fb538995940b64a5bbbc43)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F17580a23-9168-c0bc-0b73-8d6d176206ee.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=a8f96e831fde8e66783938ebe27bfac0)
todo行を下に集めたり
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F72f8a581-7c3e-7519-fcff-6a3c4aacfb36.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=60f21b51abf52ee6197a6421bfb56eb9)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F7944ec97-c355-edb1-0408-f35151519dea.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=29690b10f3f037c4531a312cc0b040ad)
Logのいらない部分を削ぎ落としたり
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2Fd5c411d3-a28e-56ba-31b5-200421ad6d7d.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=c95cfaeffeec391e1526985794e411af)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2Fe719483c-9e16-10a9-7c15-335ea1fe5b14.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=7287372ea3e04dc6cfa6bc8838390f10)
csvのカラムを入れ替えたり
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2F62e00c95-1aee-abb2-8257-3f58b5287478.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=8f4cb80ac8eb520a7fc1c3ba17256847)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F113398%2Fb6dee319-b9f4-6441-881b-523ee3bf3a16.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=dab8e5f10bbac7ae9fb8f9a55e55c198)
コツ
- カーソル位置に左右されないようなストロークにすること
- 3文字消す
xxx
ではなく 次の空白まで消すdf
とか - 繰り返す前に一度行頭に移動する
^
とか - 慣れないうちはfilterは
/
でハイライトされる箇所を見ながら組み立てると良い - mapの方も普通に操作して試してみれば良い
Vim力の向上と共に飛躍的にできることが増えてもう戻れなくなる!
やってみよー!
(思いつきでテキトー書いたわりに破綻はしなかった...かな?)