vi – Tips ~ソート編~
2010年1月22日 金曜日 | その他
こんにちは、プロダクトデザイン部の豊田です。
久しぶりに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での正規表現について書いてみようと思います。
ではまた。