wc -lでは文末に改行がないファイルの行数を正しく数えられない

2018/01/24

最後に改行がある場合は以下の通り問題ない。

wc -lは改行の数を数えるため、最後に改行がないと本当の行数より1少ない数を返してしまう。

対策としては、grep -c ''で空文字に合致する行数を求めることで代用したり、awkのENDとNRを活用したり、sedの現在の行数を出力する=と最終行$を活用したりする方法がある。

どれを使うべきかについては、イディオム的に世間に普及しているgrep -c ''か、意味的に分かりやすいawk 'END{print NR}'がいいと思う。

これは性能面で見ても間違いない。

ただgrepもawkもwc -lには性能面で敵わない。数GBのファイルの行数を数えることはほとんどないと思うので実質問題になることはないが、以下のコードで正確な行数が最速で取得できる。

tail -c 1は末尾から1byteシークしてデータを読むだけなので、どれだけファイルが大きくても即座に最後の1byteを返してくれる。取得した最後の1byteにwc -lをパイプすると改行かどうかがわかるので、wc -l < $fnameした値に1を足せばいいのかどうかの判定材料にする。ただしファイルが空の時とファイルが空ではないが文末に改行がついていない時を場合分けしなければいけないので、はじめにファイルサイズが0かどうかを確認している。
条件分岐が混在していてわかりずらいので、後半の条件分岐を計算式に書き換えてみる。

-Linux
-, ,