ファイル処理を行うにあたって、ファイルの中身を検索したい場面は頻繁に訪れます。そこで便利なコマンドがgrepコマンドです。
本稿ではgrepコマンドの基本から各種オプションまでを解説します。
grepコマンドの用法
grepコマンドの基本的な使い方は以下のようになります。
$ grep 正規表現 ファイル名
(※「$ 」はコマンド受付中のマークです。既に表示されているので皆さんが入力する必要はありません)
正規表現というのは「いくつかの文字列を一つの特別な文字や形式で表す表現方法」と説明されます。ここでは難しく考えないで「検索したい文字」程度の意味に考えておいてください。
grepコマンドを使ってみよう
それでは「tdhk.txt」というファイルに都道府県名のリストが書きこまれている場合を例に使い方を見ていきましょう!(ここではファイル名を「都道府県」になぞらえて “tdhk.txt” としていますが、実際にはどんな名前でも構いません)
実際にコマンドを試してみたい方のために都道府県名や県庁所在地名のリストを作りましたので、必要に応じてご活用下さい。
» 都道府県名のリスト
hokkaido aomori iwate miyagi akita yamagata fukushima ibaraki tochigi gunma saitama chiba tokyo kanagawa niigata toyama ishikawa fukui yamanashi nagano gifu shizuoka aichi mie shiga kyoto osaka hyogo nara wakayama tottori shimane okayama hiroshima yamaguchi tokushima kagawa ehime kochi fukuoka saga nagasaki kumamoto oita miyazaki kagoshima okinawa
» 閉じる
» 県庁所在地名のリスト
sapporo aomori morioka sendai akita yamagata fukushima mito utsunomiya maebashi saitama chiba shinjuku yokohama niigata toyama kanazawa fukui kofu nagano gifu shizuoka nagoya tsu otsu kyouto osaka koube nara wakayama tottori matsue okayama hiroshima yamaguchi tokushima takamatsu matsuyama kochi fukuoka saga nagasaki kumamoto oita miyazaki kagoshima naha
» 閉じる
» 都道府県名と県庁所在地名のリスト
hokkaido sapporo aomori aomori iwate morioka miyagi sendai akita akita yamagata yamagata fukushima fukushima ibaraki mito tochigi utsunomiya gunma maebashi saitama saitama chiba chiba tokyo shinjuku kanagawa yokohama niigata niigata toyama toyama ishikawa kanazawa fukui fukui yamanashi kofu nagano nagano gifu gifu shizuoka shizuoka aichi nagoya mie tsu shiga otsu kyoto kyouto osaka osaka hyogo koube nara nara wakayama wakayama tottori tottori shimane matsue okayama okayama hiroshima hiroshima yamaguchi yamaguchi tokushima tokushima kagawa takamatsu ehime matsuyama kochi kochi fukuoka fukuoka saga saga nagasaki nagasaki kumamoto kumamoto oita oita miyazaki miyazaki kagoshima kagoshima okinawa naha
» 閉じる
例えば、”kyoto” という単語が「tdhk.txt」というファイル内に存在するかどうかは次のように調べることができます。
$ grep kyoto tdhk.txt
これの結果はつぎのようになります。
kyoto
これを “kyoto” ではなく “kyouto” にした場合、何も表示されません(実際にやってみましょう)。
では、”kyo” で検索した場合はどうなるでしょうか?
$ grep kyo tdhk.txt
↓
tokyo kyoto
“kyo” という文字列を含む行が出力されました。
試しに “yama” で検索すると以下のようになります。
$ grep yama tdhk.txt
↓
yamagata toyama yamanashi wakayama okayama yamaguchi
このように、grepコマンドは該当する文字列があればそれを全て表示する、というコマンドであることがお分かり頂けたと思います。因みに、検索したい単語はシングルクォーテーション、またはダブルクォーテーションで囲んでもgrep可能です!
(ダブルクォーテーションを使った例)
$ grep "yama" tdhk.txt
● ● ●
Linuxを使うにあたって、grepで出てきた沢山の結果からさらに条件に合うものを抽出したい、といった場面に出くわすことがしばしばあります。こういう時はgrepコマンドを複数回使うことでほとんど解決します。
grepコマンドで「and検索」
grepコマンドで絞り込んだ結果に対して、さらに条件を加えて検索したい場合はパイプラインを使います(BACK SPACEキーの隣りのキーの「|」という文字を「パイプ」といいます)。
パイプはコマンドの結果を次のコマンドに受け渡すという機能をもちます。grepの出力結果以外でもlsコマンドの結果に対して
$ ls | grep test.txt
のようにすればディレクトリ内のファイルを検索することもできます。この例だとlsコマンドの結果をさらにgrepするという操作になります。lsコマンドの結果をgrepするからといって、次のようには書けません。
(ダメな例)
$ grep test.txt ls
これだとlsというファイルもしくはディレクトリを検索することになってしまいます。
● ● ●
それでは、先ほどの “yama” の検索結果をさらに絞り込み、”u” という文字列を含むものだけを取り出してみましょう。
$ grep yama tdhk.txt | grep u
↓
yamaguchi
無事、”yamaguchi” という文字列が得られました。これは “yama” という文字列を含み、かつ、”u” という文字列を含む行を抽出する、という「and検索」になっています。
2回目のgrepコマンドが同じ “tdhk.txt” というファイルを対象としていると考えて次のように書くと意図しない結果になります。
(ダメな例)
$ grep yama tdhk.txt | grep u tdhk.txt
↓
fukushima gunma fukui gifu shizuoka yamaguchi tokushima fukuoka kumamoto
「grep yama tdhk.txt」のコマンドが無視されてしまいました。通常は
「grep 文字列 検索対象」
と書きますが、パイプで繋いだ場合は検索対象の部分が前置されることになります。これは英語の関係代名詞の用法で目的語が前置されている、というイメージに近いです。
● ● ●
この他、パイプラインを使わずに「ドット+アスタリスク」でand検索する方法もあります。
$ grep yama.*u tdhk.txt
↓
yamaguchi
grepを2回使うよりもこちらの方がタイピングが簡単ですね!
因みに「&」に「かつ」という意味があることを知っている方なら「yama&u」や「yama&&u」でも検索できるのではないか、と思われるかもしれませんが、この場合の「&」はバックグラウンド処理の命令として認識されてしまいます。もしそうでなくとも「”yama” かつ “u” でもあるような文字列」(そんなものは存在しません)を検索しようとしますので、「”yama” という文字列を含み、かつ、”u” という文字列を含む行を抽出する」という操作にはなりません。
● ● ●
それでは “yama” という文字列を含むか、または、”u” という文字列を含むものを抽出する、という「or検索」をしたいときはどうすればよいのでしょうか?
grepコマンドで「or検索」
大抵のコマンドには拡張的な機能として、「オプション」が整備されています。grepコマンドも例外ではなく、知っていると便利なものから、普段ほとんど使わないようなものまで、様々なオプションが用意されています。
» grepコマンドのオプション
● ● ●
usageを確認するために「grep –help」と打ち込んでみると、以下のようなオプションのリストが表示されます(環境によっては若干の違いがあるかもしれません)。
-E, --extended-regexp PATTERN is an extended regular expression (ERE) -F, --fixed-strings PATTERN is a set of newline-separated fixed strings -G, --basic-regexp PATTERN is a basic regular expression (BRE) -P, --perl-regexp PATTERN is a Perl regular expression -e, --regexp=PATTERN use PATTERN for matching -f, --file=FILE obtain PATTERN from FILE -i, --ignore-case ignore case distinctions -w, --word-regexp force PATTERN to match only whole words -x, --line-regexp force PATTERN to match only whole lines -z, --null-data a data line ends in 0 byte, not newline Miscellaneous: -s, --no-messages suppress error messages -v, --invert-match select non-matching lines -V, --version print version information and exit --help display this help and exit --mmap ignored for backwards compatibility Output control: -m, --max-count=NUM stop after NUM matches -b, --byte-offset print the byte offset with output lines -n, --line-number print line number with output lines --line-buffered flush output on every line -H, --with-filename print the filename for each match -h, --no-filename suppress the prefixing filename on output --label=LABEL print LABEL as filename for standard input -o, --only-matching show only the part of a line matching PATTERN -q, --quiet, --silent suppress all normal output --binary-files=TYPE assume that binary files are TYPE; TYPE is `binary', `text', or `without-match' -a, --text equivalent to --binary-files=text -I equivalent to --binary-files=without-match -d, --directories=ACTION how to handle directories; ACTION is `read', `recurse', or `skip' -D, --devices=ACTION how to handle devices, FIFOs and sockets; ACTION is `read' or `skip' -R, -r, --recursive equivalent to --directories=recurse --include=FILE_PATTERN search only files that match FILE_PATTERN --exclude=FILE_PATTERN skip files and directories matching FILE_PATTERN --exclude-from=FILE skip files matching any file pattern from FILE --exclude-dir=PATTERN directories that match PATTERN will be skipped. -L, --files-without-match print only names of FILEs containing no match -l, --files-with-matches print only names of FILEs containing matches -c, --count print only a count of matching lines per FILE -T, --initial-tab make tabs line up (if needed) -Z, --null print 0 byte after FILE name Context control: -B, --before-context=NUM print NUM lines of leading context -A, --after-context=NUM print NUM lines of trailing context -C, --context=NUM print NUM lines of output context -NUM same as --context=NUM --color[=WHEN], --colour[=WHEN] use markers to highlight the matching strings; WHEN is `always', `never', or `auto' -U, --binary do not strip CR characters at EOL (MSDOS) -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)
沢山のオプションが用意されていることが分かりますね!
● ● ●
» 閉じる
さて、or検索は正規表現による検索を可能とする「-E」オプションによって、次のように実行できます。
$ grep -E 'w|t' tdhk.txt
↓
iwate akita yamagata tochigi saitama tokyo kanagawa niigata toyama ishikawa kyoto wakayama tottori tokushima kagawa kumamoto oita okinawa
これは “w” もしくは “t” のいずれかの文字が含まれる行を検索するコマンドです。パイプにはコマンドの実行結果を引き継ぐ機能のほか、「または」という意味をもっており、「w|t」というのは「”w” または “t”」を表しています。なお、上の例ではシングルクォーテーションで囲ってありますが、ダブルクォーテーションでも動きます。
また、or検索はパターンマッチングを調べる「-e」オプションによっても可能です。
$ grep -e w -e t tdhk.txt
これは “w” にマッチする文字列と “t” にマッチする文字列を同時に検索するコマンドです。多くのウェブサイトでは主にこちらの方法が紹介されているようです。
実は、オプションを使わずパイプ文字をエスケープすることでor検索することができます。
$ grep 'w\|t' tdhk.txt
grep以外にもパターンマッチングを調べるコマンドとして、awkやsedなどがあります。
その他の便利なオプション
上記以外によく使われるオプションをご紹介します。
「-v」オプション
:特定の文字列を含まない行を表示
$ grep -v a tdhk.txt
↓
tochigi tokyo fukui gifu mie kyoto hyogo tottori ehime kochi
「-c」オプション
:特定の文字列を含む行数を表示
$ grep -c a tdhk.txt
↓
37
「-A」オプション
:特定の文字列を含む行から下に指定行だけ表示
$ grep -A 5 tokyo tdhk.txt
↓
tokyo kanagawa niigata toyama ishikawa fukui
「-B」オプション
:特定の文字列を含む行から上に指定行だけ表示
$ grep -B 5 tokyo tdhk.txt
↓
ibaraki tochigi gunma saitama chiba tokyo
「-C」オプション
:特定の文字列を含む行の前後を指定行だけ表示
$ grep -C 5 tokyo tdhk.txt
↓
ibaraki tochigi gunma saitama chiba tokyo kanagawa niigata toyama ishikawa fukui
「-n」オプション
:特定の文字列を含む行と行番号を表示(ファイル処理の際に便利です)
$ grep -n kyo tdhk.txt
↓
13:tokyo 26:kyoto
その他にも色々なオプションがあります。
「-i」オプション
:大文字と小文字を区別せず検索する
「-h」オプション
:検索結果にファイル名を表示しない(ファイルの多いディレクトリ内で使うことが多い)
「-H」オプション
:検索結果と一緒にファイル名を表示する(「-H」オプションの逆)
「-l」オプション
:該当する文字列を含むファイル名のみ表示する(ファイルの多いディレクトリ内で使うことが多い)
「-L」オプション
:該当する文字列を含まないファイル名のみ表示する(「-l」オプションの逆)
「-o」オプション
:特定の文字列に一致した文字だけを表示する(単体ではあまり使わないイメージがあります)
「-r」オプション
:ディレクトリ内も検索対象とする
● ● ●
取り敢えずはこのくらいで十分でしょうか?この他にも紹介していないオプションがありますので、必要に応じてusageを確認してください。
今回はgrepコマンドの基本的な使い方についてまとめました。シェルスクリプトを書く際にもよく使われますし、ファイル内検索やディレクトリの検索で頻繁に使用するコマンドなので是非慣れておきたいですね!