(Linux)lookコマンドの使い道

4-1.文字列検索

関連記事はコチラ
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の処理時間が遅いのは謎のままです)

コメント

タイトルとURLをコピーしました