前々回、いろいろなプログラミング言語やファイルフォーマットに対応できるメタプラグイン「vim-polyglot」を紹介し、前回はvim-polyglotによってインストールされるCSVフォーマット用のプラグイン「chrisbra/csv.vim」について取り上げた。その際にも述べたように、chrisbra/csv.vimはあまりにも便利な多機能プラグインなので、今回から数回に渡ってはこのプラグインについて掘り下げたい。

chrisbra/csv.vimでできることは前回一覧で掲載した通りだ。この機能一覧を大きく仕分けると、chrisbra/csv.vimでは次のような操作を行うことができることになる。

  • CSVデータの閲覧
  • CSVデータ内の移動
  • CSVデータの編集
  • CSVデータの分析
  • CSVデータの比較
  • CSVデータの変換


このうち、今回はCSVデータの閲覧に関する機能を取り上げる。これらの機能を知っているのと知っていないのとでは、CSVファイルの扱いやすさがかなり変わってくるはずだ。いきなり全部覚えることは難しいので、使用頻度が高い機能から随時覚えてもらえればと思う。

CSVをテーブル形式で表示

CSVファイル向けの設定を何も行っていない場合、VimでCSVファイルを開くと次のように表示される。ただのテキストファイルだ。

CSVファイルに対して何も設定が行われていないVim

通常、折り返しの設定になっていると思うので、1行が長いCSVデータは折り返しが入ってかなり見にくい(CSVデータは郵便局が公開しているデータ「郵便番号データダウンロード 住所の郵便番号(ローマ字) zip形式 - 日本郵便」のうち、東京都のものを使っている)。

chrisbra/csv.vimを有効にしたVimでこのファイルを開くと次のようになる。

chrisbra/csv.vimによるシンタックスハイライト

カンマはパイプ区切りになり、それぞれ色付けられている。行は折り返さなくなり、CSVデータとしては閲覧しやすい状態になる。

スプレッドシートアプリケーションにおいて、通常セルは縦横の線が揃った表形式になっている。chrisbra/csv.vimでは「CSVArrangeColumn」というコマンドにこの表示へ切り替える機能が実装されている。つまり、「:%CSVArrangeColumn」のように実行すれば、ファイル全体を縦横が揃った表形式に変換することができる。スプレッドシートに慣れている場合、この表示はなじみやすいだろう。

:%CSVArrangeColumnで表形式表示

chrisbra/csv.vimにはもう一つ、表形式表示機能が用意されている。編集中のウィンドウはそのままに、表形式に整えた状態をプレビューとして別のウィンドウに開くというものだ。同機能はCSVTabularizeコマンドに実装されており、「:%CSVTabularize」でファイル全体をテーブル形式でプレビュー表示させることができる。

「:%CSVTabularize」で表形式プレビュー表示

どちらの機能も1行だけ実施することも、選択した行に対しても実施することができる。

ただし、この2つの機能はある程度実験的な機能だと思っておいたほうがよい。いくつかの機能はchrisbra/csv.vimのほかの機能との連動がうまくいかないからだ。基本的には、あくまでも閲覧するときに使うもの、と考えておくとよいだろう。編集機能などを組み合わせてデータを保存すると困った事態に陥ることがあるので、あまりお薦めできない。この2つの機能は閲覧専用と覚えておきたい。

列をハイライト

デフォルトの表示(表形式表示ではない場合)だと、上下の行のどの部分が同じ列なのかわかりにくい。この場合、CSVHiColumnコマンドで列をハイライト表示させることができる。

:CSVHiColumnでカレント列をハイライト

「:CSVHiColumn!」でハイライト表示を取り消すことができる。以降のコマンドにおいても共通していることが多いのだが、コマンドに続けて「!(エクスクラメーション)」を書いておくと、その機能が無効化される。また、引数として列番号を指定できることが多く、列番号を指定した場合にはその列に対して処理が行われる。列番号が指定されていない場合には、カーソルのある列が処理の対象となることが多い。

ヘッダ行を固定表示

スプレッドシートでは、1行目を固定表示して使うケースもよくあるだろう。例えば、1行目がヘッダ(項目名)になっているため常に表示しておきたい、といった場合だ。chrisbra/csv.vimでは、「CSVHeader」で同じことができる。

「:CSVHeader」で1行目を固定表示

「:CSVHeader」を実行すると、上部に別ウィンドウが開き、そこに1行目が固定表示されるようになる。CSVHeaderに行数を指定すると、その行数分が固定表示の対象となる。

ヘッダ列目を固定表示

CSVHeaderの列版となるコマンドが「CSVVHeader」だ。1列目を常に表示しておきたい場合にはこのコマンドを使用することになる。

「:CSVHeader」で1行目を固定表示

CSVHeaderやCSVVHeaderを使用すれば、ヘッダ部分を常に表示させておくことができる。閲覧しやすさがぐっと向上するはずだ。

列でソート

スプレッドシートアプリケーションを操作していると、特定の列の値でデータをソートしたいこともあるだろう。これは、「:CSVSort」で実施できる。

「:CSVSort」で列を整列

「:CSVSort」で列で整列

この機能も、ぜひ使い方をマスターしておきたい。

列で検索

Vimの検索機能が強力であることはこれまで何度も取り上げているが、chrisbra/csv.vimではこの検索を特定の列に対して行うことができる。「CSVSearchInColumn」がそのコマンドだ。

:CSVSearchInColumn 列番号 /パターン/ で列ごとに検索可能

この機能も便利なので、ぜひ覚えておいてほしい。

列を折りたたみ

Vimはテキストの折りたたみ機能を提供している。折りたたみたい範囲を選択してから「zf」で実施できる。この機能を使用すると、閲覧したい行だけを表示させておくことができるので便利だ。chrisbra/csv.vimではこれを列に対して実施できる。Vimが折りたためるのは基本的に行単位なので、chrisbra/csv.vimの機能で列単位に折りたたむわけだ。

「:CSVVertFold」で1列目からカレント列までの折りたたむ。列番号を指定して1列目からそこまで折りたたむこともできる

列単位での折りたたみはCSVVertFoldコマンドで実施する。1列目からカレント列までが折りたたみの対象となる。引数に列番号を指定すれば、1列目から指定した列までを折りたたむことができる。1列目から特定の列までがタグ的なデータになっていて比較時に読む必要がないことなどがあり、そういった場合にCSVVertFoldコマンドで折りたたんでおくと読みやすくなる。

CSVを転置する

表を扱っていると、縦と横の項目を入れ替えたいときがある。こうした処理は通常「転置」と呼ばれる。chrisbra/csv.vimでは、この転置をCSVTransposeコマンドで行うことができる。

CSVTransposeで縦横の項目の入れ替え(転置)が可能

転置は、ユーザーによっては喉から手が出るほど欲しい、必須の機能であるはずだ。転置のためだけに、chrisbra/csv.vimを使うというのもアリだろう。

chrisbra/csv.vimのコマンド体系ほか

ここまでのコマンドでお気づきかと思うが、chrisbra/csv.vimのコマンドは「CSV○○ 列番号」のような規則になっている。列番号の指定がなければカーソルがあるカレント列が処理の対象となる。また、「:CSV○○!」でその機能を無効化するという仕組みにもなっている(一部例外はある)。

コマンド名が長くて冗長に思えるかもしれないが、chrisbra/csv.vimのコマンド名は意外と覚えやすい。また、CSVを省略して入力することもできるし、コマンド名は途中まででも使用できる。使っていけばどこまで省略可能なのかもわかってくるだろう。思いの外、短い入力で処理が行えることに気づくはずだ。

処理速度は対象とするCSVファイルのサイズと、PCの性能に強く依存している。当然ながら高速なPCを使っていれば大きなサイズのファイルも快適に編集できる。一方、仮想環境やクラウド上のサーバなどスペックが限定されている環境だと、それなりの遅さになってくる。この辺りは、お使いの環境によるとしか言えない。

CSVデータをVimで閲覧することに最初は違和感を覚えるかもしれない。だが、慣れてくるとスプレッドシートアプリケーションを起動するよりも、こちらで処理するほうが手っ取り早くなるはずだ。ぜひとも、”将来の手抜き”のために今練習して覚えてしまってほしい。

本連載で使っている設定ファイル

本連載で使っている設定ファイル(~/.vimrc)は以下の通りだ。

"dein Scripts=============================
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=~/.cache/dein/./repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('~/.cache/dein/.')
  call dein#begin('~/.cache/dein/.')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/./repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here
  call dein#add('junegunn/seoul256.vim')
  call dein#add('vim-airline/vim-airline')
  call dein#add('vim-airline/vim-airline-themes')
  call dein#add('preservim/nerdtree')
  call dein#add('tpope/vim-commentary')
  call dein#add('tpope/vim-fugitive')
  call dein#add('fholgado/minibufexpl.vim')
  call dein#add('dense-analysis/ale')
  call dein#add('junegunn/fzf', {'build': './install --all'})
  call dein#add('junegunn/fzf.vim')
  call dein#add('sheerun/vim-polyglot')

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

" seoul256
let g:seoul256_background = 233
colo seoul256

" vim-airline
let g:airline_powerline_fonts = 1
let g:airline_theme = 'molokai'

" NERDTree
"  <C-o> open NERDTree
nnoremap <silent> <C-o> :NERDTreeToggle<CR>

" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>

" fzf
nnoremap <silent> fzf :Files<CR>
nnoremap <silent> ls :Buffers<CR>

"End dein Scripts=========================

set number
syntax on
set whichwrap=b,s,[,],<,>,~,h,l
set cursorline
set incsearch
set hlsearch
set ignorecase

付録 chrisbra/csv.vim が提供する代表的な機能

コマンド 内容
CSVWhatColumn カーソルが何列目にあるか
CSVWhatColumn! 同列1行目の内容を表示
CSVNrColumns 最大列数を表示(先頭から10行で判断)
CSVSearchInColumn /パターン/ 現在の列をパターンで検索
CSVSearchInColumn 列番号 /パターン/ 指定した列をパターンで検索
CSVHiColumn 現在の列を強調表示
CSVHiColumn 列番号 指定した列を強調表示
CSVHiColumn! 列の強調表示を解除
CSVArrangeColumn テーブル形式での表示へ切り替え(実験的機能)
CSVTabularize テーブル形式でのプレビュー表示
CSVDeleteColumn 現在の列を削除
CSVDeleteColumn 列番号 指定した列を削除
CSVHeader 1行目を別ウィンドウで表示
CSVHeader 行数 先頭から指定行数分を別ウィンドウで表示
CSVHeader! 開いた行ヘッダウィンドウを閉じる
CSVVHeader 1列目を別ウィンドウで表示
CSVVHeader 列番号 行頭から指定列数分を別ウィンドウで表示
CSVVHeader 開いた列ヘッダウィンドウを閉じる
CSVSort 現在の列でファイルをソート
CSVSort 列番号 現在の列でファイルをソート
CSVSort! 現在の列でファイルを逆順にソート
CSVSort! 列番号 現在の列でファイルを逆順にソート
CSVColumn 現在の列をコピー
列番号CSVColumn 指定した列をコピー
CSVMoveColumnor 現在の列を最後の列の右側へ移動
CSVMoveColumn 列番号 列番号 最初に指定した列を、2つ目に指定した列の右側へ移動
CSVSumCol 現在の列の合計を出力
CSVSumCol 列番号 指定した列の合計を出力
CSVSumRow 行の合計を出力
CSVNewRecord 新しい行を作成
CSVNewDelimiter デリミタ 区切り文字を変更
CSVConvertData データをほかの形式に変換
CSVDuplicates 列番号 指定した列で重複している行を出力
CSVAnalyze 現在の列を分析する(値とその数、割合など)
CSVAnalyze 列番号 指定した列を分析する(値とその数、割合など)
CSVVertFold 1列目から現在の列を折りたたむ
CSVVertFold 列番号 1列目から指定した列までを折りたたむ
CSVVertFold! 列の折りたたみを解除する
CSVTranspose 列と行を入れ替える(転置)
CSVAddColumn 現在の列の右側に新しい列を追加
CSVAddColumn 列番号 指定した列の右側に新しい列を追加
CSVDupColumn 現在の列を右側に複製
CSVDupColumn 列番号 指定した列を右側に複製
CSVSubstitute 列番号/パターン/文字列/ 指定した列で置換
CSVColumnWidth 列ごとの最大文字数を出力
CSVCountCol 現在の列内の値の数を出力
CSVCountCol 列番号 指定した列内の値の数を出力
CSVMaxCol 現在の列内の最大値を出力
CSVMaxCol 列番号 指定した列内の最大値を出力
CSVMaxMin 現在の列内の最小値を出力
CSVMaxMin 列番号 指定した列内の最小値を出力
CSVAvgCol 現在の列内のデータの平均値を出力
CSVAvgCol 列番号 指定した列内のデータの平均値を出力
PopVarCol 現在の列の母集団分散を出力
PopVarCol 列番号 指定した列の母集団分散を出力
SmplVarCol 現在の列の標本分散を出力
SmplVarCol 列番号 指定した列の標本分散を出力
PopStdCol 現在の列の母標準偏差を出力
PopStdCol 列番号 指定した列の母標準偏差を出力
SmplStdCol 現在の列の標本標準偏差を出力
SmplStdCol 列番号 指定した列の標本標準偏差を出力
移動キー 内容
「Ctrl」+「→」 次の列へ移動
L 次の列へ移動
W 次の列へ移動
「Ctrl」+「←」 前の列へ移動
E 前の列へ移動
H 前の列へ移動
列を上へ移動
K 列を上へ移動
列を下へ移動
J 列を下へ移動
キー 内容
↩️ 現在の列と一致しないすべての行を動的に折りたたむ
Space 現在の列と一致するすべての行を動的に折りたたむ
BS 動的フィルタから最後のアイテムを削除
設定項目 内容
g:csv_delim デフォルトのデリミタ
g:csv_no_conceal 1に設定するとデリミタ部分を|で視覚的に表示(デフォルトは設定されていない)
g:csv_highlight_column ‘y’に設定するとカーソルがある列を自動でハイライト
b:csv_headerline ヘッダの行数を指定。0を指定するとヘッダとしてのハイライトが行われなくなる