巨大ファイルHEADからみるかTAILからみるか
何の話?
このツイートと関連するレスを見ていると、みんな head
が好きなんですね。
僕が一般に「巨大なテキストファイルに向き合う」必要に駆られたとき、
入口としてのlessを超えるものはない と認識していることから、この記事を書くに至りました。
ただし本件に限ったはなしであれば、対象がCSVであること、集計という目的がすでに明確であること、
そもそも10,000行という要件が与えられていることなどから、正解は他にも多数あろうことはお断りしておきます。
で、lessって?
less
。ファイルや標準入力のテキストを読み込んで、画面にその一部を表示してくれるだけのプログラムです。
実に目的はシンプルですが、 manpage
を覗いてみるとリッチな機能を秘めていることは伺えるでしょう。
less は 正体不明の巨大なテキストと向き合う上で、最良の入口 となるものなのです。
- 雑に開いて中身を覗き見できる
- 覗き見の範囲を予め指定する必要がない
- 気になった部分を指定して他の処理に渡すことができる
一つずつ見ていきましょう。
開いて中身を覗き見できる
$ less <filename>
$ cat <filename> | less
世間にテキストエディタは数多く存在しますが、巨大な入力ファイルというのは何かと障壁になるものです。
less
はあくまでも「中身を見ること」にフォーカスしており、いかに巨大なファイルでも画面表示に必要な領域だけをメモリに乗せて、表示してくれます。
覗き見の範囲を予め指定する必要がない
冒頭に述べた通り、みなさん head
が好きなようですが…
$ head -n <lines> <filename>
$ cat | head -n <lines> <filename>
少し使い勝手に難がありましょう。
- 1行あたりの桁数が巨大だと結局巨大なままになる
- 何行を見れば妥当なのか予め判断する必要がある
例えば、次のような試行錯誤を繰り返すことも。
$ head hugefile -n 100
...
# 💭 JSONかよ。しかも1オブジェクトで100行超えるのか。もうちょっと行数増やすか…
$ head hugefile -n 1000
...
# 💭 ゲッ どこかにクソ長い行があるじゃん。削らなきゃ…
こんな試行錯誤をするくらいなら、はじめから less
で見るのが良いでしょう。
$ less hugefile
行数など気にせず開いたら、 j
(下の行へ移動)と k
(上の行へ移動)などを駆使して好きに移動できます。
( less --help
より一部抜粋 )
e ^E j ^N CR *
Forward one line (or N lines).
y ^Y k ^K ^P *
Backward one line (or N lines).
f ^F ^V SPACE *
Forward one window (or N lines).
b ^B ESC-v *
Backward one window (or N lines).
これらがpartialな読み込みで(メモリにすべてのファイルを乗せることなく)実行できるため、ほとんどストレスなく実行できます。
(操作方法は覚えましょう 🦾)
パイプでの外部プログラムへの引き渡し
less
の最も気にいっている点として、パイプがあります。
パイプ自体はシェルを扱う方なら何を今更、と思われるでしょうが、
less
は less で気になる部分を指定して、そのまま他の処理を呼び出す ことができるのです。
-
less
で開く(以下の操作はless
内での操作) - カーソルを移動して、気になる範囲の先頭へ移動する
-
ma
でマークをつける - カーソルを移動して、気になる範囲の末尾へ移動する
-
|a
と入力してパイプを呼び出す - 任意のプログラムを指定する
標準入力に対応しているプログラムであれば、好き放題に渡せます。
標準入力に対応しているプログラムでなければ、 cat を介してファイルに出力してしまっても良いでしょう。
- (前略)
-
|a
と入力してパイプを呼び出す cat > hoge.txt
まとめ
- ファイルを開く前に考える必要がない
- フォーマットは妥当だろうか?
- 指定する行数は妥当だろうか?
- 見た結果をそのまま外部に出力・引き渡すことができる
less
の利点、少しでもお伝えできたでしょうか。
一切の思考を放棄して、まずは less
してみる、という生活はなかなかに快適なものです。
ぜひ一度さわってみてください。
蛇足
まあ、今どきは大変優秀なテキストエディタ、Vi...
© tpope
sual Studio Codeが第一選択になるんでしょうけどね。
巨大ファイルも開ける、外部プログラムの呼び出しなぞお手の物。
時代遅れのオッサンのつぶやきでございました。
Discussion
結局本題の「データ分析のため先頭の1万行だけを取り出したCSVを作る」はどうやってlessで実現するんでしょうか?
$ less huge.csv
10000gbj
|^cat >part.csv
ですかね。
このコメントは実際に触って書いてないんで、ミスがあるかもしれませんが。