関連記事はコチラ
https://life-is-command.com/linux-command-beginner/
lookというコマンドがあります。
たとえば、impeachmentという英語の綴りを忘れてしまった時に、
look impeaと入力すると、以下のようにimpeaから始まる英単語がすべて表示されます。
$ look impea impeach impeached impeaches impeaching impeachment impeachment's impeachments
(Linux入門はコチラ→中級者のためのLinuxコマンド入門)
lookコマンドの使い道
ん〜。impeaから始まる単語がわかったところで、このコマンドの良さが見い出せません。
日本人の私にとって、英単語の綴りがわからなくなる場合は、まずimpleaから思い出せない気がするからです。
lookコマンドの書式は、
look [-dfa] [-t termchar] 文字列 [ファイル]
それぞれのオプションの意味です。
-d 辞書で使用されているアルファベットと数字だけを比較対象とする
-f アルファベットの大文字、小文字を区別しない
-a 別の辞書 /usr/share/dict/web2 を使用する
-t 文字列の終端文字を指定する
ファイルに何も指定しないと
/usr/share/dict/words
が指定されたことと同一になります。
look impea
は、
grep ^impea /usr/share/dict/words
と結果は同じです。
比べてみましょう
$ look impea | cat -n 1 impeach 2 impeached 3 impeaches 4 impeaching 5 impeachment 6 impeachment's 7 impeachments $ grep ^impea /usr/share/dict/words | cat -n 1 impeach 2 impeached 3 impeaches 4 impeaching 5 impeachment 6 impeachment's 7 impeachments
結果は同じでした。
grepと同じことができるようです。
lookのメリットとは……。
man lookを読む
man でlookの説明を読んでみます。
look は、 file の各行のうち、 string で指定された文字列で始まっている行を表示する。 look は二分検索を使っているため、file で指定するファイルは ソートしておかなければならない。 ( look で -d オプションを使うときにはソートするときの sort(1) にも -d を使い、-f オプションを使うときは sort(1) でも -f を使うこと)
二分検索をするため、どうやら結果を得るまでの時間が早いように思えます。
では実際に時間を計測してgrepと比べてみます。
今回は検索する文字列として/usr/share/dict/wordsには存在しない文字列asdfを指定してみました。
time look asdf real 0m0.016s user 0m0.016s sys 0m0.000s time grep ^asdf /usr/share/dict/words real 0m0.003s user 0m0.000s sys 0m0.000s
この結果だけを見るとlookよりもgrepの方が早いように見えます。
ではlookコマンドのソースを読んで見ましょう。
まずはソース取得。
~$ apt-get source bsdmainutils ~$ cd bsdmainutils-9.0.6 ~/bsdmainutils-9.0.6$
次にtreeコマンドでディレクトリ構造を確認します。
tree -d | nl 1 . 2 ├── debian 3 │ ├── calendars 4 │ ├── lintian 5 │ ├── patches 6 │ └── source 7 ├── patches 8 └── usr.bin 9 ├── banner 10 ├── calendar 11 │ └── calendars 12 │ ├── de_AT.ISO_8859-15 13 │ ├── de_DE.ISO8859-1 14 │ ├── fr_FR.ISO8859-1 15 │ ├── hr_HR.ISO8859-2 16 │ ├── hu_HU.ISO8859-2 17 │ ├── ru_RU.KOI8-R 18 │ └── uk_UA.KOI8-U 19 ├── col 20 ├── colcrt 21 ├── colrm 22 ├── column 23 ├── from 24 ├── hexdump 25 ├── look 26 ├── lorder 27 ├── ncal 28 ├── ul 29 └── write 30 28 directories
lookコマンドのソースファイルは25行目のディレクトリにありそうです。
lookコマンドをビルドする
apt-get source bsdmainutilsで取得したファイル群から
lookディレクトリの中を確認してみます。
~$ find usr.bin/look -type f usr.bin/look/look.1 usr.bin/look/pathnames.h usr.bin/look/look.c usr.bin/look/Makefile
どうやらlook.cがlookコマンドのソースファイルのようです。
中身を見る前に、ビルドして動作するか確認してみます。
cd usr.bin/look make ~/bsdmainutils-9.0.6/usr.bin/look$ make cc -include ../../freebsd.h -O2 -g -c -o look.o look.c look.c:49:10: error: expected declaration specifiers or ‘...’ before string coo nstant __FBSDID("$FreeBSD$"); ^ look.c: In function ‘main’:ai look.c:141:20: error: ‘SIZE_T_MAX’ undeclared (first use in this function)ti if (sb.st_size > SIZE_T_MAX) ^ look.c:141:20: note: each undeclared identifier is reported only once for each function it appears in ../../config.mk:42: recipe for target 'look.o' failed make: *** [look.o] Error 1 ~/bsdmainutils-9.0.6/usr.bin/look$
ビルドできませんでした。
私が使っているのはDebianなので、パッチが必要なようです。
パッチを当てます。
~/bsdmainutils-9.0.6/usr.bin/look$ patch < ../../debian/patches/look.diff patching file look.c
これでビルドできるようになりましたので、makeします。
~/bsdmainutils-9.0.6/usr.bin/look$ make cc -include ../../freebsd.h -O2 -g -c -o look.o look.c cc -o look look.o
実行してみます。同時に時間も計測。
~/bsdmainutils-9.0.6/usr.bin/look$ time ./look real 0m0.001s user 0m0.000s sys 0m0.000s
あれ?何か変です。今回実行したlookは処理時間が短くなっています。
さらに/usr/bin/lookと、grepも計測してみます。
~$ time look asdf real 0m0.018s user 0m0.016s sys 0m0.000s ~$ time grep asdf /usr/share/dict/words real 0m0.003s user 0m0.000s sys 0m0.000s
まとめると、asdfという存在しない文字列を探すのにかかる各コマンドの時間は、
/usr/bin/look 0.018s
ソースからビルドしたlook 0.001s
grep 0.003s
でした。
grepよりも処理時間が短いということは、lookコマンドの使い道が見い出せそうです。
(もともと入ってた/usr/bin/lookの処理時間が遅いのは謎のままです)
コメント