LEXUES BLOG

レキサスブログ

vi – Tips ~ソート編~

こんにちは、プロダクトデザイン部の豊田です。

久しぶりにviネタを書いてみたいと思います。
今日のテーマはソート。並び替えです。


gVimではsortコマンドでテキストを行単位でソートできます。
例えば、以下のようなテキストに対して、

1: Name:Python
2: Name:Scala
3: Name:PHP
4: Name:Java
5: Name:Ruby

:1,5sort

1: Name:Java
2: Name:PHP
3: Name:Python
4: Name:Ruby
5: Name:Scala

1,5の指定はsortコマンドの適用範囲を行番号で指定しています。
何も指定しない場合は、テキストファイル全体に適用されます。

さて、単純な行ソートであれば上述の方法でよいのですが、
以下のような複数行にまたがったブロックをソートする場合はどうでしょうか。

1: ———-
2: Name:Python
3: Year:1990
4: ———-
5: Name:Scala
6: Year:2003
7: ———-
8: Name:PHP
9: Year:1995
10: ———-
11: Name:Java
12: Year:1995
13: ———-
14: Name:Ruby
15: Year:1995
16: ———-

このようなテキストデータをNameでソートしたい場合、
単純にsortコマンドを使用すると上手くいきません。

:1,16sort

1: ———-
2: ———-
3: ———-
4: ———-
5: ———-
6: ———-
7: Name:Java
8: Name:PHP
9: Name:Python
10: Name:Ruby
11: Name:Scala
12: Year:1990
13: Year:1995
14: Year:1995
15: Year:1995
16: Year:2003

アプローチとしては、一旦データブロックを一行に連結した後に、
ソートしてブロックに戻すという方法が考えられます。

1) 行を連結する前に文末を@でマークしておく。

:1,16g/^Name/-1,/^Year/-1s/$/@/g

1: ———-@
2: Name:Python@
3: Year:1990
4: ———-@
5: Name:Scala@
6: Year:2003
7: ———-@
8: Name:PHP@
9: Year:1995
10: ———-@
11: Name:Java@
12: Year:1995
13: ———-@
14: Name:Ruby@
15: Year:1995
16: ———-

2) 行を連結。

:1,16g/Name/-1,/Year/j

1: ———-@ Name:Python@ Year:1990
2: ———-@ Name:Scala@ Year:2003
3: ———-@ Name:PHP@ Year:1995
4: ———-@ Name:Java@ Year:1995
5: ———-@ Name:Ruby@ Year:1995
6: ———-

3) ソート。

:1,5sort

1: ———-@ Name:Java@ Year:1995
2: ———-@ Name:PHP@ Year:1995
3: ———-@ Name:Python@ Year:1990
4: ———-@ Name:Ruby@ Year:1995
5: ———-@ Name:Scala@ Year:2003
6: ———-

4) ブロックに戻す。

:1,5s/@ /^M/g (※^MはCtrl+v Ctrl+mで改行コードを意味します。)

1: ———-
2: Name:Java
3: Year:1995
4: ———-
5: Name:PHP
6: Year:1995
7: ———-
8: Name:Python
9: Year:1990
10: ———-
11: Name:Ruby
12: Year:1995
13: ———-
14: Name:Scala
15: Year:2003
16: ———-

これは「入門vi」で紹介されている方法ですが、
globalコマンドを巧みに利用したステキなTipsだと思います。

では、Yearでソートする場合はどうでしょうか。
2) から 3) の間で、カラムの入替えを行えばよいでしょう。

2′) カラムを入替える。

:1,5s/(Name:[^@]*)@ (Year:.*)$/2@ 1/g

1: ———-@ Year:1990@ Name:Python
2: ———-@ Year:2003@ Name:Scala
3: ———-@ Year:1995@ Name:PHP
4: ———-@ Year:1995@ Name:Java
5: ———-@ Year:1995@ Name:Ruby
6: ———-

3) ソート。

:1,5sort

1: ———-@ Year:1990@ Name:Python
2: ———-@ Year:1995@ Name:Java
3: ———-@ Year:1995@ Name:PHP
4: ———-@ Year:1995@ Name:Ruby
5: ———-@ Year:2003@ Name:Scala
6: ———-

3′) カラムを戻す。

:1,5s/(Year:[^@]*)@ (Name:.*$)/2@ 1/g

1: ———-@ Name:Python@ Year:1990
2: ———-@ Name:Java@ Year:1995
3: ———-@ Name:PHP@ Year:1995
4: ———-@ Name:Ruby@ Year:1995
5: ———-@ Name:Scala@ Year:2003
6: ———-

4) ブロックに戻す。

:1,5s/@ /^M/g

1: ———-
2: Name:Python
3: Year:1990
4: ———-
5: Name:Java
6: Year:1995
7: ———-
8: Name:PHP
9: Year:1995
10: ———-
11: Name:Ruby
12: Year:1995
13: ———-
14: Name:Scala
15: Year:2003
16: ———-

正規表現は非常に奥が深く強力です。
次回はgVimでの正規表現について書いてみようと思います。
ではまた。

この記事のライター

みなさまからのご連絡をお待ちしております。

CONTACT US