UNIX/Linuxの部屋 コマンド:grep

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド grep ファイルから指定のパターンにマッチする行を検索する このエントリーをはてなブックマークに追加

最終更新


UNIX/Linux の grep コマンドは、ファイルの中から指定の文字列を検索するコマンドである。複数ファイルからの検索や、複数条件での検索、正規表現のパターン指定、特定パターン除外指定、ディレクトリをたどる再帰的検索などを行うことができる。


grep コマンドの基本的な使い方
あるファイルの中に、指定の文字列を含む行を表示する。例えば、sample.dat の中の「hoge」という文字列を含む行を表示したい場合、
% grep hoge sample.dat
とする。また、
% grep hoge file1 file2 file3
% grep hoge dir/*
などとすると、複数のファイルについて調べることができる。

検索したい文字列には正規表現を使うことができる。例えば
% grep '[a-z]' sample.dat
とすると、a〜z を含む行を全て表示する。ただし、grep コマンドはデフォルトでは限定正規表現しか扱えないことに注意 (-E オプションを参照)。

FreeBSD や Linux は他 grep に比べて高機能である grep (GNU grep) コマンドを標準採用しているが、Solaris などはデフォルトの grep は (GNU grep と比べると) 低機能で、-e オプションや -E オプションを使うことができない。Solaris の場合、/usr/xpg4/bin/grep が多少は高機能な grep となっているが、GNU grep ほどではない。

grep コマンドの用途はとても広い。
  • /var/log/ にあるログファイルから、特定のメッセージを抜き出す
  • /var/log/ にあるログファイルから、特定の日付のみのログを抜き出す
  • /usr/include/ から、特定のマクロがどこで定義されているか調べる
grep コマンドを使いこなせていないとしたら、その人の UNIX のスキルは知れたものである。ぜひ有効な使い方を覚えてほしい。

grep コマンドのオプション一覧まとめ
grep コマンドのオプションは以下のとおり。
-num マッチした文字列の前後 num 行を表示する。
-A [num] または --after-context=[num] マッチした文字列の後に続く num 行を表示する
-B [num] または --before-context=[num] マッチした文字列の前の num 行を表示する
-a または --text バイナリファイルであったとしても、テキストファイルのように扱う
-b マッチした行のオフセット (開始バイト数) を表示
-C -2と同じ
-c または --count テキスト中に文字列が含む行の行数を表示する
-e [パターン] または --regexp=[パターン] 明示的に検索パターンを指定する
-E [パターン] または --extended-regexp=[パターン] 拡張正規表現を使う
-F 固定文字列として検索する
-f [file] または --file=[file] ファイル file 中の文字列を検索パターンとして使う
-h または --no-filename 出力行の先頭のファイル名を表示しない
-i または --ignore-case 大文字小文字を区別しない
-l または --files-with-matches オプション 指定文字列を含むファイル名を表示する
-L または --files-without-match 指定文字列を含まないファイル名を表示
-n または --line-number マッチした行の行番号を表示する
-o または --only-matching マッチした該当箇所のみを表示する
-P または --perl-regexp Perl 互換の正規表現 (PCRE) を使う
-r または --recursive ディレクトリを再帰的にたどって、ファイルを検索する
-s または --no-messages エラーメッセージを抑制する(ファイルに対しての permission denied など)
-w または --word-regexp ファイル中の指定文字列が独立している場合だけマッチしたものとみなす
-x または --line-regexp 指定文字列がそのまま1行にあるものだけマッチしたものとみなす
-v または --invert-match 指定文字列を「含まない」行を表示
-Z または --decompress 圧縮したファイルを grep する
--line-buffered 出力バッファリングにおいて、行バッファリングとする

grep コマンドのオプション詳細説明
▷ -[行数] マッチした文字列の前後 num 行を表示する。
デフォルトは -0。つまりマッチした行のみを表示するということ。grep -3 は、該当行に加え、その前の 3行とそのあとの3行を表示する。

grep -3 は grep -A3 -B3 と同じ意味である。
▷ -A[行数] または --after-context=[行数]
マッチした文字列の後に続く N 行を表示する。-A3 は、該当行に加え、そのあとの 3行を表示する。
▷ -B[行数] または --before-context=[行数]
マッチした文字列の前の N 行を表示する。-B3 は、該当行に加え、その前の 3行を表示する。
▷ -a または --text
バイナリファイルであったとしても、テキストファイルのように扱う。grep コマンドはバイナリファイルに対してはマッチした行を表示するのではなく、一致したことだけを伝える。
% grep a /bin/ls
バイナリファイル /bin/ls に一致しました
→ または Binary file /bin/ls matches
しかしながら、テキストファイル内に一部不正データが混入している場合など、本当はテキストファイルとして扱ってほしい場合は、-a または --text オプションを使うことで、テキストファイルのように取り扱うことができる。バイナリファイル内の文字列を検索したい場合は string コマンドの使用を検討すること。
▷ -b マッチした行のオフセット (開始バイト数) を表示
% grep -b foo sample.txt
0:foo
18:aafoobb
⇒ foo の行は sample.txt の 0バイト目から始まり、aafoobb の行は sample.txt の 18バイト目から始まることがわかる
▷ -C[行数]
-[行数] と同じく、マッチした行の前後 N 行を表示する。
▷ -c または --count
テキスト中に文字列を含む行の行数を表示する。-v と組み合わせると、含まない行数を表示する。
% grep -c hoge a.txt
5
→ a.txt には hoge を含む行が 5行ある
% grep -c -v hoge a.txt
8
→ hoge を含まない行は 8行ある
複数ファイルに対して実行すると、ファイル名と行数を表示する。
% grep -c hoge *
a.txt:5
b.txt:9
c.txt:0

% grep -c hoge * | sort -t: -k2n
c.txt:0
a.txt:5
b.txt:9
→ ヒットした行数の昇順でソート
▷ -e [パターン] または --regexp=[パターン]
明示的に検索パターンを指定する。パターンは正規表現として扱われる。

パターンが 1つだけの場合、以下の 2つは同じである (-e オプションを付けても付けなくてもよい)
% grep hoge sample.txt
% grep -e hoge sample.txt

-e オプションは複数個のパターンを指定するときによく使用される。
例えば「rwx」または「r-x」を含む行を検索しようとして、
% ls -l | grep 'rwx' 'r-x'
とすると、grep は 「r-x」というファイルを見付けようとしてエラーになってしまう。こういう場合は -e オプションを複数個指定し、
% ls -l | grep -e 'rwx' -e 'r-x'
とすればよい。低機能版の grep には -e オプションは効かないので注意。
▷ -E [パターン] または --extended-regexp=[パターン]
拡張正規表現を使う。デフォルトでは 「?+|{}()」などは普通の文字として扱われてしまうので、「foo」と「bar」を含む行を表示しようとして、
% grep 'foo|bar' sample.txt
としても、'foo|bar' という普通の文字列だと認識されてしまう。
% grep -E 'foo|bar' sample.txt
だと拡張正規表現として扱われるので、うまくいく。低機能版の grep には -E オプションは効かないので注意。grep -E は egrep とほぼ同じである。
▷ -F 固定文字列として検索する。
. * ? などのメタキャラクタを指定しても、正規表現としての意味を持たなくなる。grep -F は、fgrep と同じである。
▷ -f [file] または --file=[file]
ファイル file 中の文字列を検索パターンとして使う。
▷ -h または --no-filename
出力行の先頭のファイル名を表示しない。grep コマンドのデフォルトでは
% grep hoge *.txt
sample1.txt: hogehoge
sample1.txt: aahoge
sample2.txt: hogefuga
のように、各行の先頭にファイル名を表示するが、-h オプションを使うと
% grep hoge *.txt
hogehoge
aahoge
hogefuga
というふうにファイル名表示を抑止する。
▷ -i または --ignore-case
大文字小文字を区別しない。
▷ -l または --files-with-matches オプション
指定文字列を含むファイル名を表示する。そのファイル内で何回マッチしたかに関わらず、ファイル名が表示されるのは一度のみである。指定の文字列を含むファイルが何個あるか数えるには
% grep -l hoge *.txt | wc -l
とする。
▷ -L または --files-without-match
指定文字列を含まないファイル名を表示。
▷ -n または --line-number
マッチした行の行番号を表示する。
% grep -n hoge *.txt
sample1.txt:26: hogehoge
sample1.txt:128: aahoge
sample2.txt:3 hogefuga
▷ -o または --only-matching
マッチした該当箇所のみを表示する。パターンマッチに加え、「切り出し」が行えるので地味に便利。

下記はログから IP アドレスっぽいものを抽出する例。このように、行の前後にある不要データは表示せず、マッチした部分のみを表示してくれるので、sed や awk などの後処理が不要になるのが便利である。
% grep -oP '\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}' access_log
17.188.53.138
103.154.198.221
103.154.198.221
103.154.198.221
21.27.83.14

上記では -P で Perl 正規表現を使っているが、拡張正規表現のみで実現する方法は下記。
% grep -oE '[0-9]{1,3}\.[0-9]{1,3}.[\0-9]{1,3}\.[0-9]{1,3}' access_log
下記は URL っぽいものを表示する例。
grep -oE 'https?:[^ "<]+' access_log
▷ -P または --perl-regexp
Perl 互換の正規表現 (PCRE) を使う。
▷ -r または --recursive
ディレクトリを再帰的にたどって、ファイルを検索する。通常の場合は "grep PATTERN [対象ファイル]" であるが、-r オプションを指定した場合は "grep -r PATTERM [対象ディレクトリ]" とする。
% grep -r hoge .
→ カレントディレクトリ以下のファイルから再帰的に hoge を検索する
% grep -r hoge dir/ dir2/
→ ディレクトリ dir と dir2 以下のファイルから再帰的に hoge を検索する
-r オプションで再帰的に検索する場合は、--include オプション・--exclude オプション・--exclude-dir オプションで絞り込むのが便利である。こちら を参照してほしい。
▷ -s または --no-messages
エラーメッセージを抑制する (ファイルに対しての permission denied など)。
▷ -w または --word-regexp
ファイル中の指定文字列が独立している場合だけマッチしたものとみなす。
% cat test
sample // 独立した文字列ではないのでマッチしない
samp // 記号や空白でかこまれた文字列はマッチする
samp2 // 数字は記号とみなされない
,samp-
(samp&
samp/
% grep -w samp test
samp
,samp-
(samp&
samp/
▷ -x または --line-regexp
指定文字列がそのまま1行にあるものだけマッチしたものとみなす。つまり
% grep -x abc

% grep '^abc$'
と等価。
▷ -v または --invert-match
指定文字列を「含まない」行を表示 (正規表現にマッチしたら除外する)。
% grep -v hoge sample.txt
→ sample.txt の、hoge を含む行を除外し、それ以外を表示する。
▷ -Z または --decompress
圧縮したファイルを grep する。
% compress file.txt
% grep -Z hoge file.txt.Z
▷ --line-buffered 出力バッファリングにおいて、行バッファリングとする。
例えば
% tail -f /var/log/syslog | grep hoge | grep -v fuga
のように tail の後に grep コマンドを 2段に重ねた場合、最初の grepコマンド が出力時にバッファリングを行なってしまうためログに追記された内容がすぐには表示されない。そのようなときは以下のように --line-buffered オプションを使うとよい (Linux と *BSD で使用可。FreeBSD は 5.3-RELEASE 以降)。
% tail -f /var/log/syslog | grep --line-buffered hoge | grep -v fuga

必ず覚えてほしいオプションは、-i、-e、-n、-v である。

Howto: 検索結果にファイル名のみを表示する
-l または --files-with-matches オプションを使うことで、該当文字列が存在するファイル名のみを表示できる。
% grep -l hoge *.txt
sample.txt
sample2.txt
影響範囲の調査のために、ある関数を呼び出しているソースを調べたり、修正すべきファイルがどれだけ残っているかを確認する目的で使用するとよい。

Howto: 正規表現ではなく固定文字列で検索するには
-F または --fixed-strings オプションを使うことで正規表現が無効になり、"." "*" "?" "[]" などがそのままの文字列として検索できる。
% grep -F a.txt *.txt

Howto: 複数条件 (OR 条件) での検索
-e オプションを複数指定することで、複数条件 (OR条件) を指定できる。
% grep -e aaa -e bbb -e ccc *.txt
正規表現で | でつなげてもよい。通常の grep なら \| とエスケープする。egrep なら | をそのままでよい。
% grep 'aaa\|bbb\|ccc' *.txt
% egrep 'aaa|bbb|ccc' *.txt

Howto: 複数条件 (AND 条件) での検索
grep をパイプで複数段つなげることで、AND 条件を指定できる。
% grep aaa *.txt | grep bbb | grep ccc
ただしこの場合は、「同一行に aaa と bbb と ccc が出現する行を検索する」という意味であることに注意。もし、「同一行でなくてもいいので、aaa と bbb と ccc が出現するファイル名を表示する」が目的であれば、-l オプションと xargs を使って、下記のようにすればよい。
% grep -l aaa *.txt | xargs grep -l bbb | xargs grep -l ccc

Howto: ディレクトリを再帰的に検索する
grep に -r オプションを付けることで再帰的にディレクトリをたどって検索することができる。
% grep -r hoge .
→ カレントディレクトリ以下のファイルから再帰的に hoge を検索する
% grep -r hoge dir/ dir2/
→ ディレクトリ dir と dir2 以下のファイルから再帰的に hoge を検索する
-r オプションで再帰的に検索する場合は、--include オプションと --exclude で絞り込むのが便利である。
% grep -r --include='*.log' hoge .
→ 対象ファイルを *.log に絞る
% grep -r --exclude='*.log' hoge .
→ *.log 以外のファイルを対象に検索する
--include オプションと --exclude オプションはファイルに対してしか効果がない。ディレクトリを除外したい場合は --exclude-dir オプションを使う。
% grep -r --exclude-dir='.svn' --exclude-dir='.git' .
→ .*.log 以外のファイルを対象に検索する
残念ながら --exclude-dir オプションは FreeBSD 11.0-RELEASE ではまだ使えないようだ。

Howto: 大文字小文字を同一視する
-i オプション指定することで、大文字小文字を区別しないようにできる。
% grep -i aaa *.txt
→ aaa でも AAA でも aAA でもマッチする。

Howto: プロセスの検索
現在実行中のプロセスから abc という表示を抜き出すには
% ps ax | grep abc (SystemV 系 UNIX なら ps -ef)
とすればよいが、プロセス実行のタイミングによっては
% ps ax | grep abc
118 ?? Ss 0:00.03 abc
760 p3 R+ 0:00.00 grep abc
と、grep 自身がマッチしてしまうことがある。こういうときは
% ps ax | grep '[ a]bc'
とすればよい。grep '[ a]bc' を実行すると、ps の出力には
760 p3 R+ 0:00.00 grep [ a]bc
となるが、[ a]bc 自体は正規表現と解釈されるので、
760 p3 R+ 0:00.00 grep [ a]bc
の行にはマッチしないわけである。まぁ、単純に
% ps ax | grep abc | grep -v grep
でもよいのだけれど。

関連コマンド
正規表現ではなく固定文字列で検索したい場合は fgrep コマンドを使う。"." や "*" などのエスケープがめんどくさい場合に有用。なお、grep -F と fgrep は同じである。

正規表現ではなく拡張正規表現で検索したい場合は egrep コマンドを使う。拡張正規表現だと、下記のように若干いまどきな感じで書くことができる。
  • "(〜)" のグルーピングで括弧をエスケープしなくてよい
  • OR を表す "|" もエスケープしなくてよい
  • "aa*" を "a+" と書ける
  • "a{0,1}" を "a?" と書ける
なお、grep -E と egrep は同じである。

gzip で圧縮されたファイルから検索したい場合は zgrep コマンドを使う。なお、FreeBSD では、grep -Z と zgrep は同じであるが、GNU grep では -Z オプションの意味が異なるため Linux などでは同じではない。

その他: 関連コマンド
>> Solaris10オンラインマニュアル(man) Solaris10 grep(1)
>> FreeBSDオンラインマニュアル(man) FreeBSD grep(1)
>> Linuxオンラインマニュアル(man) Linux grep(1)

読み方 grep (UNIXコマンド) [ぐれっぷ] このエントリーをはてなブックマークに追加

ed コマンドの "g/RE/p"(Global Regular Expression Print) の略。