C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

egrepの結果の表示順序とsort、シェルを便利にオレオレ関数を作りましょう。

(※今回はリアルにLinuxの入門講座を受講している程度の方へ、って感じのtipsみたいな形になりました。)

あるディテくトリーに、 1 2 3 4 5 6 7 8 9 というファイル名で同じデータの書き込まれたテキストファイルがあったとしましょう。

% /bin/ls  
1 2 3 4 5 6 7 8 9

こんな感じネU・x・U

ここでファイルの内容は、 'abc' と書かれているだけとしましょう。

% cat 1
abc
% diff 1 2 && diff 2 3 && diff 3 4 && diff 4 5 && diff 5 6 && diff 6 7 && diff 7 8 && diff 8 9 && echo EQ
EQ

こんな感じネU・x・U

(※参考として、 diff は同一ならば true(=0) 、 不同一ならば false(1) を処理系に返します。&&は左辺が true(=0) ならば右辺を実行します。上記が echo EQ を評価すると言う事は全ての diff が同一と結果を返した事になります。)

さて、ではここで egrep (≈`grep -e`) したとしましょう。 ls と同じ順序で表示されると思いますか?^−^

% egrep -nr abc 
1:1:abc
2:1:abc
3:1:abc
9:1:abc
8:1:abc
7:1:abc
4:1:abc
5:1:abc
6:1:abc

1,2,3までは大方の予想通りの表示と思います。しかし続きで9,8,7が来るとは恐らく多くの方は思わなかったのでは無いでしょうか。そして最後に4,5,6が表示されるなんてね。

この現象が何故発生するかと言うと、 egrep がディレクトリーの操作を行う為に呼び出すOSのAPIがファイルやディレクトリーについてソート済みでは無いからです。ls は表示内容を名前でソートしてから表示してくれているだけです。この状況は必ずしも再現できるとは保証できませんが、次のような操作で簡単に再現できるかもしれません。

% echo abc > 1
% echo abc > 2
% echo abc > 3
% echo abc > 9
% echo abc > 8
% echo abc > 7
% echo abc > 4
% echo abc > 5
% echo abc > 6

と、言う訳で egrep は sort と常に組み合わせになる様に仕込んで置くと便利が良いかもしれません。

% g(){ egrep -nr $1 | sort; }  

引数を扱うのでaliasでは微妙かと思いますのでシェルスクリプトによる関数として定義する例としました。これを使ってみましょう。気に入ったなら .zshrc などに関数定義を加えて置けば良いでしょう。

% g abc                       
1:1:abc
2:1:abc
3:1:abc
4:1:abc
5:1:abc
6:1:abc
7:1:abc
8:1:abc
9:1:abc

g というコマンド(正確にはシェルスクリプト関数)で「現在のディレクトリ以下に対し egrep -nr し sort して表示する」という機能を実装した事になります。

こうした自分用にシェルを使い易くする為の関数やaliasや変数などは気づいたらどんどん .zshrc (とか .bachrc とか)に定義して使う様にすると、シェルの便利さに目覚めるかもしれませんよ^−^

(※ちなみにegrepの表示順がOSのAPIによる列挙の順序に依存する様な事を書きましたが、これはOSのファイル列挙用のAPI、またその下部にあるファイルシステムそのものの実装やAPIも関係しているものと思います。)