TL;DR
grep
に色を付ける際は、--color=always
ではなく--color=auto
を使いましょう、という話です。
環境
$ zsh --version
> zsh --version
> zsh 5.7.1 (x86_64-apple-darwin17.7.0)
背景と問題
タスクを進める過程で、以下のような構造のCSVファイルから、col1
またはcol2
が特定の文字列である行を抽出してcol3
の値が大きい順にソートする、というような処理がありました。
col1,col2,col3
a,a,10
a,a_1,20
a,a_2,5
a,a_3,10
a_1,a,25
a_1,a_1,30
a_1,a_2,20
a_1,a_3,10
例としてここでは、col1
またはcol2
の値がa
である行を抽出する必要があったとします。
シンプルに、a,
でgrep
したものをsort
すれば目的の出力が得られるはずだと考えて、以下のコマンドを実行しました。
$ grep 'a,' test.csv | sort -t ',' -k 3 -rn
a,a_1,20
a,a_3,10
a,a_2,5
a_1,a,25 # numerical sortされていない
a,a,10 # 同上
あれ? なんで4、5行目が降順ソートされていないんだ?
パイプを使わずにsort
単体で挙動を試したところ、col3
での降順ソートは問題なく実行できる様子。
となるとgrep
に原因があるのか?とアタリをつけて試行錯誤すること数十分(ツラい)。
問題のコマンドの出力をファイルにリダイレクトしてみた時、ようやく原因が分かりました。
原因
以下が、先程のコマンドの出力をテキストファイルにリダイレクトした中身です。
[01;31m[Ka,[m[Ka_1,20
[01;31m[Ka,[m[Ka_3,10
[01;31m[Ka,[m[Ka_2,5
a_1,[01;31m[Ka,[m[K25
[01;31m[Ka,[m[K[01;31m[Ka,[m[K10
一見して「ナニコレ?」と面食らってしまいましたが、調べた結果、この特殊文字は色付け用のANSI escape codeだと分かりました。
.zshrc
でexport GREP_OPTIONS="--color=always"
としていたので、grep
の検索パターンにマッチした部分に色付け用の特殊文字が挿入されたわけです。
今回の問題は、それによって4、5行目のcol3
が数値として解釈不可能な文字列になってしまい、降順数値ソートがうまく働かなかった、ということですね。
色付け設定が原因だと分かったところで、上記の行をコメントアウトして再度実行すると案の定上手くいきました。
grep
の--color
オプション
「とはいえ色付けできたほうが見やすいし、何かないかな」とgrep
の--color
について調べてみると、never
,auto
,always
のいずれかが指定可能であり、それぞれ以下のような仕様だと分かりました。
-
never
:色を付けない -
auto
:標準出力がターミナルに繋がっている場合のみ色を付ける(パイプやリダイレクトの際は色付けしない) -
always
:常に色付け(文字列を変更するので後続処理に影響を与える)
こうして見ると、基本的に**--color=always
に設定するメリットは薄い**と言ってしまってよさそうです。
視認性を高めるためにaliasや環境変数で指定する分には、auto
でおそらく充分でしょう。
例外があるとすれば、grep
の結果が長大化したときにless
に渡して閲覧する、というような状況でしょうか。
grep
の--color
オプションは、実行時に渡した値が環境変数のそれに優先して使われるので、その際にだけgrep --color=always
としてless
にパイプすれば、目的は果たせるかと思います。
参考にさせていただいた記事
grepコマンドに色をつける
Different results in grep results when using --color=always option
教訓
問題の根本の原因は、プログラムを書き始めた頃の自分が「とりあえずbashよりzshのが高機能らしい」「この設定にしとけば便利らしい」と、聞きかじりの知識でターミナル環境を構築してしまったところにありました。
至極当たり前のことですが、先駆者のコードや設定を使わせてもらう際は、その目的と影響範囲を正しく認識しておくのが大切ですね...
ただ、そのマインドを維持できるのもある程度の体系的な知識が有ってこそだと思いますので、今後も精進していきたいと思います。
過去の自分が何気なくコピペした.zshrc
に時を超えて困らされるという、ある意味貴重な自戒の機会でした。
このささやかなハマり事例が、もし誰かのお役に立ったなら幸いです。