- 技術 💻
grepコマンドの使い方|オプション早見表と実務の逆引き(実行結果つき)
grepコマンドとは、ファイルや他のコマンドの出力から、指定した文字列や正規表現に一致する「行」を取り出すコマンドです。ログからエラー行だけを探す、ソースコード全体から関数の呼び出し箇所を探す、設定ファイルから特定の項目を確認する、といった場面で毎日のように使います。
この記事では、サンプルのログファイルとソースコードのフォルダを用意し、すべてのコマンドを実際に実行して、その出力をそのまま載せています(GNU grep 3.11)。オプションの早見表に加えて、「エラー行の前後を見たい」「AかつBの行」「特定フォルダを除外したい」といった実務の逆引き、スクリプトで使う終了ステータス、見落としやすい文字コードと改行コード、よく比べられるripgrep(rg)との速度と挙動の違いまで確認しました。
grepのオプション早見表
| オプション | 意味 | 例 |
|---|---|---|
-i |
大文字・小文字を区別しない | grep -i error app.log |
-v |
一致しない行を表示 | grep -v INFO app.log |
-n |
行番号を付ける | grep -n WARN app.log |
-c |
一致した行数を表示 | grep -c ERROR app.log |
-w |
単語全体で一致 | grep -w cat words.txt |
-o |
一致した部分だけを表示 | grep -oE 'user=[a-z]+' app.log |
-r / -R |
フォルダ内を再帰的に検索(-R はシンボリックリンクもたどる) |
grep -rn TODO . |
-l / -L |
一致した / しなかったファイル名だけ | grep -rl login src |
-h / -H |
ファイル名を表示しない / する | grep -rh TODO src |
-E |
拡張正規表現(| + ? {} () がそのまま使える) |
grep -E 'WARN|ERROR' |
-F |
正規表現を使わず文字どおりに検索 | grep -F '1.5' price.txt |
-P |
Perl互換正規表現(先読み・後読み、\d) |
grep -oP '(?<=user=)\w+' |
-e |
パターンを指定(複数可、- で始まる語にも) |
grep -e WARN -e ERROR |
-f |
パターンをファイルから読む | grep -f patterns.txt app.log |
-A / -B / -C |
一致行の後 / 前 / 前後の行も表示 | grep -C1 ERROR app.log |
-m |
最初のN件で止める | grep -m1 ERROR app.log |
-q |
何も表示せず、終了ステータスだけ返す | grep -q ERROR app.log |
-s |
「ファイルがない」などのエラーを表示しない | grep -s x *.log |
-a |
バイナリファイルもテキストとして扱う | grep -a ERROR bin.dat |
--include |
対象にするファイル名のパターン | --include='*.js' |
--exclude / --exclude-dir |
除外するファイル / フォルダ | --exclude-dir=node_modules |
--color=auto |
一致部分に色を付ける | 多くの環境で初期設定済み |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「grepコマンドの使い方|オプション早見表と実務の逆引き(実行結果つき)」
基本の書き方
grep [オプション] パターン [ファイル...]
コマンド | grep [オプション] パターン
この記事で使うサンプルのログ app.log です。
2026-09-28 10:00:01 INFO Server started port=8080
2026-09-28 10:00:05 INFO user=alice login ok
2026-09-28 10:01:12 WARN slow query 1520ms table=orders
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:01:14 INFO retry 1/3
2026-09-28 10:02:30 error Failed to send mail to bob@example.com
2026-09-28 10:03:00 INFO user=bob login ok
2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
2026-09-28 10:04:00 INFO user=alice logout
$ grep ERROR app.log
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
grepは初期状態で大文字・小文字を区別します。6行目の小文字の error は出てきません。
$ grep -i error app.log
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:02:30 error Failed to send mail to bob@example.com
2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
パターンはシングルクォートで囲む習慣を付けると安全です。* や $、スペースをシェルが先に解釈してしまうのを防げます。
主要オプションの実行結果
行番号・件数・否定
$ grep -n WARN app.log
3:2026-09-28 10:01:12 WARN slow query 1520ms table=orders
$ grep -c ERROR app.log
2
$ grep -vc INFO app.log # INFOではない行の数
4
-c は「一致した行の数」です。1行に2回出てきても1と数えます。出現回数を数えたいときは、後で紹介する -o と wc -l を組み合わせます。
-w:単語として一致
$ grep cat words.txt
cat
catalog
concat
the cat sat
$ grep -w cat words.txt
cat
the cat sat
-w を付けると、catalog や concat のような「一部に含む」行を除けます。変数名や関数名を探すときに便利です。
-o:一致した部分だけ取り出す
$ grep -oE 'user=[a-z]+' app.log
user=alice
user=bob
user=alice
$ grep -oE 'user=[a-z]+' app.log | sort | uniq -c
2 user=alice
1 user=bob
-o + sort | uniq -c は、ログの集計の定番です。IPアドレスやエラーコード別の件数を出すときにも使えます。
-F:記号を文字どおりに探す
$ grep '1.5' price.txt
price: 1.5
price: 105
price: 1x5
$ grep -F '1.5' price.txt
price: 1.5
正規表現では . が「任意の1文字」なので、105 や 1x5 にも一致しました。IPアドレス、バージョン番号、URLなど記号を含む文字列を探すときは -F を付けると意図どおりになり、正規表現の処理がない分、速く動きます。
正規表現:基本(BRE)と拡張(ERE)
grepの初期設定は基本正規表現(BRE)です。-E を付けると拡張正規表現(ERE)になります。違いは、一部の記号にバックスラッシュが必要かどうかです。
| 意味 | 基本(grep) |
拡張(grep -E) |
|---|---|---|
| 1回以上 | 'a\+' |
'a+' |
| 0回か1回 | 'a\?' |
'a?' |
| 回数指定 | '[0-9]\{4,\}' |
'[0-9]{4,}' |
| グループ | '\(ab\)*' |
'(ab)*' |
「または」は、基本正規表現では |、拡張正規表現では | と書きます。
実際に、基本正規表現のまま | を書くと、「WARN|ERROR」という文字列そのものを探すため、何も見つかりませんでした。
$ grep 'WARN|ERROR' app.log; echo "exit=$?"
exit=1
$ grep 'WARN|ERROR' app.log # 基本正規表現なら | と書く
$ grep -E 'WARN|ERROR' app.log # 拡張正規表現ならそのまま
2026-09-28 10:01:12 WARN slow query 1520ms table=orders
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
迷ったら grep -E を使うと、他の言語の正規表現に近い書き方ができます。なお、egrep / fgrep はGNU grep 3.8以降で非推奨になっており、代わりに grep -E / grep -F を使います。
| よく使う記号 | 意味 | 例 |
|---|---|---|
^ |
行頭 | '^2026-09-28 10:0[0-1]' |
$ |
行末 | 'ok$' |
. |
任意の1文字 | '1.5' |
[abc] / [^abc] |
どれか1文字 / それ以外の1文字 | '[0-9]' |
* |
直前の0回以上 | 'a*' |
\b / \< \> |
単語の境界(GNU拡張) | '\bcat\b' |
$ grep -E '[0-9]{4,}ms' app.log # 4桁以上のミリ秒(1秒以上の遅延)
2026-09-28 10:01:12 WARN slow query 1520ms table=orders
$ grep -oP '(?<=user=)\w+' app.log # -P の後読みで「user=」の後ろだけ
alice
bob
alice
実務の逆引き
エラー行の前後を見る(-A / -B / -C)
$ grep -A1 'db timeout' app.log # 後ろ1行(After)
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:01:14 INFO retry 1/3
$ grep -B1 'db timeout' app.log # 前1行(Before)
2026-09-28 10:01:12 WARN slow query 1520ms table=orders
2026-09-28 10:01:13 ERROR db timeout table=orders
$ grep -n -C1 ERROR app.log # 前後1行(Context)
3-2026-09-28 10:01:12 WARN slow query 1520ms table=orders
4:2026-09-28 10:01:13 ERROR db timeout table=orders
5-2026-09-28 10:01:14 INFO retry 1/3
--
7-2026-09-28 10:03:00 INFO user=bob login ok
8:2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
9-2026-09-28 10:04:00 INFO user=alice logout
-n と組み合わせると、一致した行は :、前後の行は - で区別され、離れたかたまりは -- で区切られます。Javaのスタックトレースのように、エラーの後ろに続く行を見たいときは -A 20 のように多めに指定します。
OR(どれかを含む)
grep -E 'WARN|ERROR' app.log
grep -e WARN -e ERROR app.log
grep -f patterns.txt app.log # patterns.txt に1行1パターン
3つとも同じ結果です。探す語が多いときは -f でファイルにまとめると管理しやすくなります。
AND(すべてを含む)
grepには「かつ」を直接書くオプションがないため、パイプでつなぎます。
$ grep ERROR app.log | grep orders
2026-09-28 10:01:13 ERROR db timeout table=orders
順番が決まっているなら grep -E 'ERROR.*orders' とも書けます。
除外する
$ grep -v -e INFO -e WARN app.log
2026-09-28 10:01:13 ERROR db timeout table=orders
2026-09-28 10:02:30 error Failed to send mail to bob@example.com
2026-09-28 10:03:45 ERROR NullPointerException at OrderService.java:42
「ERRORを探すが、既知のtimeoutは除く」なら grep ERROR app.log | grep -v timeout のように、探す → 除く、の順につなぎます。
フォルダ全体を検索し、特定のフォルダを除く
次のようなプロジェクトで TODO を探しました。
src/main/auth.js src/main/auth.py src/test/auth.test.js
node_modules/lib/index.js
$ grep -rn TODO .
./src/main/auth.py:2: # TODO: add rate limit
./src/main/auth.js:2: // TODO: validate input
./node_modules/lib/index.js:1:// TODO: vendor code
$ grep -rn --include='*.js' TODO .
./src/main/auth.js:2: // TODO: validate input
./node_modules/lib/index.js:1:// TODO: vendor code
$ grep -rn --exclude-dir=node_modules TODO .
./src/main/auth.py:2: # TODO: add rate limit
./src/main/auth.js:2: // TODO: validate input
--include はファイル名の絞り込みで、フォルダは除外しません。node_modules の中の .js も出てきました。依存ライブラリやビルド結果のフォルダは --exclude-dir で除くのが基本です。複数あるときは --exclude-dir={node_modules,.git,dist} と書けます。--include のパターンは、シェルに展開されないようクォートで囲みます。
ファイル名だけ知りたい
$ grep -rl login src # 含むファイル
src/test/auth.test.js
src/main/auth.py
src/main/auth.js
$ grep -rL TODO src # 含まないファイル
src/test/auth.test.js
$ grep -rh TODO src # ファイル名なしで中身だけ
# TODO: add rate limit
// TODO: validate input
-l の結果を xargs に渡すと、「〜を含むファイルをまとめて開く・置換する」といった操作につなげられます(ファイル名に空白があり得るときは grep -rlZ ... | xargs -0 ...)。
件数を数える
| 数えたいもの | コマンド |
|---|---|
| 一致した行の数 | grep -c ERROR app.log |
| 一致した回数(1行に複数回も数える) | grep -o ERROR app.log | wc -l |
| ファイルごとの行数 | grep -rc ERROR logs/ |
| 種類ごとの件数 | grep -oE 'ERROR [A-Za-z]+' app.log | sort | uniq -c | sort -rn |
最初の1件だけ・ログをリアルタイムに
$ grep -m1 ERROR app.log
2026-09-28 10:01:13 ERROR db timeout table=orders
tail -f app.log | grep --line-buffered ERROR # 流れてくるログからERRORだけ
tail -f の後にさらにパイプでつなぐときは、--line-buffered を付けると1行ずつすぐに出力されます。
パイプと組み合わせる
| 目的 | コマンド |
|---|---|
| プロセスを探す | ps aux | grep '[n]ginx' |
| 待ち受けポートを確認 | ss -lntp | grep ':8080' |
| コマンド履歴から探す | history | grep docker |
| 設定ファイルのコメントと空行を除く | grep -Ev '^\s*(#|$)' nginx.conf |
| Gitの管理下だけ検索 | git grep -n TODO |
ps aux | grep nginx では、実行したgrep自身の行も表示されます。'[n]ginx' と書くと、grepのコマンド行([n]ginx という文字列)には一致しなくなるため、除けます。プロセスを探すだけなら pgrep -a nginx も便利です。
終了ステータス:スクリプトで使う
| 終了ステータス | 意味 |
|---|---|
| 0 | 一致する行があった |
| 1 | 一致する行がなかった |
| 2 | エラー(ファイルがない、読めないなど) |
$ grep -q ERROR app.log; echo $?
0
$ grep -q FATAL app.log; echo $?
1
$ grep -q x nofile.log; echo $?
grep: nofile.log: No such file or directory
2
$ if grep -q ERROR app.log; then echo "エラーあり"; fi
エラーあり
「見つからない」は1で、エラーの2とは区別されています。シェルスクリプトで set -e を使っていると、一致なし(1)でもスクリプトが止まる点に注意します。見つからなくても続けたいときは grep ... || true とします。
また、-q を付けて一致が見つかった場合は、ほかのファイルでエラーがあっても0になります。
$ grep -q ERROR app.log nofile.log; echo $?
0
「-」で始まる文字列を探す
$ grep '-v' dash.txt; echo "exit=$?" # -v がオプション、dash.txt がパターンと解釈される
exit=1
$ grep -e '-v' dash.txt
-v option
$ grep -- '-v' dash.txt # -- 以降はオプションとして扱わない
-v option
最初の例は、-v がオプション、dash.txt が検索パターンと解釈され、ファイルではなく標準入力を読みにいきます(端末では入力待ちで止まったように見えます)。- で始まる語は -e か -- で渡します。
文字コード・改行コード・バイナリ
Shift_JISのファイルは、そのままでは一致しない
$ grep 'エラー' sjis.txt; echo "exit=$?"
exit=1
$ iconv -f SHIFT_JIS -t UTF-8 sjis.txt | grep 'エラー'
売上エラー
端末がUTF-8、ファイルがShift_JISだと、同じ「エラー」でもバイト列が違うため一致しません。iconv や nkf でUTF-8に変換してから検索します。
日本語と「.」、ロケールの影響
$ echo '売上エラー' | LC_ALL=C grep -o 'エ.ー'; echo "exit=$?"
exit=1
$ echo '売上エラー' | LC_ALL=C.UTF-8 grep -o 'エ.ー'
エラー
ロケールがC(LANG が未設定の環境を含む)だと、. は1バイトに一致するため、3バイトある「ラ」に一致しませんでした。日本語を正規表現で扱うときは、LANG や LC_ALL がUTF-8になっているかを確認します(locale コマンドで確認できます)。
Windowsの改行(CRLF)で $ が効かない
$ grep 'ok$' crlf.txt; echo "exit=$?"
exit=1
$ grep -c $'\r' crlf.txt
2
CRLFのファイルでは、行末の直前に \r があるため ok$ に一致しません。grep -c $'\r' で \r を含む行があるか確かめ、sed 's/\r$//' や dos2unix で改行を変換するか、grep $'ok\r\\?$' のように \r も許すパターンにします。
バイナリファイル
$ grep ERROR bin.dat
grep: bin.dat: binary file matches
$ grep -a ERROR bin.dat | cat -v
abc^@ERROR
NUL文字などを含むファイルは中身を表示せず「binary file matches」とだけ出ます。中身を見たいときは -a を付けます。一部だけ文字化けしたログファイルがこの扱いになることもあります。
ripgrep(rg)との比較
ripgrep(コマンド名 rg)は、grepと同じ目的の高速な検索ツールです。VS Codeの検索機能の内部でも使われています。
探す範囲の違い
先ほどのフォルダを Git リポジトリにし、.gitignore に node_modules/ を書き、隠しフォルダ .cache/ にもTODOを置いて比べました(ripgrep 14.1.0)。
$ grep -rn TODO . # (.git の中の一致は省略)
./src/main/auth.py:2: # TODO: add rate limit
./src/main/auth.js:2: // TODO: validate input
./.cache/x.txt:1:TODO hidden
./node_modules/lib/index.js:1:// TODO: vendor code
$ rg -n TODO
src/main/auth.py:2: # TODO: add rate limit
src/main/auth.js:2: // TODO: validate input
rgは初期状態で、.gitignore に書かれたもの・隠しファイル・バイナリファイルを除外します。オプションなしで「自分が書いたコードだけ」を探せるのが大きな特徴です。一方、grep -r は .git フォルダの中まで検索しました。すべてを対象にしたいときは rg -uuu を使います。
速さの比較
約570MB・2,000個のログファイル(2コアの環境)で、同じ語を検索した時間です(各2〜3回実行)。
| コマンド | 時間 |
|---|---|
grep -r 'ERROR timeout' . |
0.44〜0.55秒 |
rg 'ERROR timeout' . |
0.10〜0.12秒 |
grep -ri 'error timeout' .(ロケールC) |
0.61〜0.62秒 |
grep -ri 'error timeout' .(ロケールC.UTF-8) |
2.39〜2.54秒 |
rg -i 'error timeout' . |
0.23〜0.30秒 |
この環境では、rgがgrepの約4倍速く、大文字・小文字を区別しない検索ではUTF-8ロケールのgrepより約10倍速い結果でした。ファイル数、ディスク、CPUのコア数で差は変わりますが、大きなフォルダを何度も検索するならrgが快適です。
| 比べる点 | grep | rg |
|---|---|---|
| 入っている環境 | ほぼすべてのLinux/macOSに標準 | 別途インストール |
| 再帰検索 | -r が必要 |
初期状態で再帰 |
| .gitignore・隠しファイル | 対象にする | 除外する |
| 正規表現 | BRE / ERE / PCRE(-P) |
Rustの正規表現(-P でPCRE2) |
| ファイルの種類で絞る | --include='*.js' |
-t js、-g '!src/test' |
| 終了ステータス | 0 / 1 / 2 | 0 / 1 / 2(同じ) |
サーバーでの調査やシェルスクリプトには標準のgrep、手元の開発でのコード検索にはrg、と使い分けるのがおすすめです。
よくある質問
Q. 複数の文字列をOR検索するには?
A. grep -E 'A|B' か grep -e A -e B です。基本正規表現のまま 'A|B' と書くと、A|B という文字列そのものを探すため一致しません。
Q. 大文字・小文字を区別せずに、単語全体で探すには?
A. grep -iw error app.log のように、オプションはまとめて書けます。行番号も付けるなら grep -inw。
Q. 特定の拡張子だけ、再帰的に検索するには?
A. grep -rn --include='*.py' 'import' . です。node_modules などを除くなら --exclude-dir も併せて指定します。
Q. 検索結果に色が付きません。
A. --color=auto を付けるか、alias grep='grep --color=auto' を設定します。パイプの先に渡すと色は付かないのが正常で、色を付けたいときは --color=always を使います(ファイルに保存すると色の制御文字も一緒に保存されます)。
まとめ
- grepは、一致する「行」を取り出すコマンド。パターンはシングルクォートで囲む
- よく使うのは
-i-v-n-c-w-o-r-l。前後を見るなら-A-B-C - ORは
-E 'A|B'、ANDはパイプ、除外は-v。記号を文字どおり探すなら-F - 再帰検索では
--exclude-dirで依存ライブラリを除く。--includeはフォルダを除外しない - 終了ステータスは 0:あり、1:なし、2:エラー。
set -eでは「なし」でも止まる - Shift_JISやCRLF、ロケールCでは、一致しないことがある
- 大きなフォルダのコード検索には ripgrep(rg)が速く、.gitignoreも考慮してくれる
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「grepコマンドの使い方|オプション早見表と実務の逆引き(実行結果つき)」
株式会社RJCでは、毎日使う基本のコマンドも、実際に試して気づいたことを仲間と教え合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。