grepは、ファイルの中から特定の文字列(パターン)を含む行を検索するLinuxの定番コマンドです。ログからERRORの行だけを抜き出したり、設定ファイルから特定のキーワードを探したり、ほかのコマンドの出力を絞り込んだりと、Linuxを使ううえで欠かせません。名前は「global regular expression print」に由来し、正規表現での検索もできます。
つまずきやすいのは、検索パターンが正規表現として扱われること(.や*が特別な意味を持つ)と、サブフォルダまで検索するには-rが必要なことです。この記事では、実機のLinux(WSLのDebian)で実際にコマンドを動かしながら、grepの使い方を整理します。
- 基本は
grep "検索文字列" ファイル名。一致する行が表示されます。 -iで大文字小文字を無視、-nで行番号、-vで一致しない行、-cで件数。- サブフォルダも検索するには
-r(再帰)を付けます。 - パターンは正規表現。記号を文字どおり探すなら
-F(固定文字列)を使います。 -oで一致部分だけ、-wで単語単位、-Eで拡張正規表現。コマンド | grep ...のように、ほかの出力を絞り込むのが定番です。
ほかの基本コマンドはよく使うLinuxコマンドまとめ、ディレクトリ移動はcdコマンド、Windowsでgrep相当のことをするならPowerShellのSelect-Stringもあわせて参考になります。
grepの基本
もっとも基本的な使い方は、grep "検索文字列" ファイル名です。指定した文字列を含む行が、そのまま表示されます。
# ファイルから ERROR を含む行を探す grep "ERROR" app.log # 出力例: # ERROR disk full # 複数ファイルをまとめて検索(ファイル名も表示される) grep "ERROR" *.log
実機でも、grep "ERROR" a.logはERROR disk fullの行を表示しました。検索文字列はクォート("...")で囲むのが安全です(スペースや記号を含む場合に特に重要)。複数のファイルを*.logのように指定すると、まとめて検索でき、どのファイルの行かも表示されます。
よく使うオプション(-i / -n / -v / -c)
grepには便利なオプションが多数あります。まず覚えたいのが、大文字小文字を無視する-i、行番号を表示する-n、一致しない行を表示する-v、件数を数える-cです。
# -i: 大文字小文字を無視(error でも ERROR がヒット) grep -i "error" app.log # -n: 行番号を表示 grep -n "ERROR" app.log # 2:ERROR disk full # -v: 一致「しない」行を表示(ノイズ除去に便利) grep -v "DEBUG" app.log # -c: 一致した行数を数える grep -c "ERROR" app.log
実機でも、-iでerrorがERRORにヒットし、-nで2:ERROR disk fullのように行番号が付き、-v "ERROR"でERRORを含まない行だけが表示されました。-vは、特定のノイズ(DEBUG行など)を除いて中身を確認したいときに重宝します。-cは件数を数えるので、「エラーが何件出たか」をすぐに把握できます。
再帰検索(-r / -l)
注意したいのが、サブフォルダの中まで検索するには-r(再帰)が必要なことです。フォルダを指定して-rを付けると、その中のすべてのファイルを検索します。ファイル名だけを知りたいときは-lを使います。
# カレント以下すべてのファイルから ERROR を検索(grep -r 相当) grep -r "ERROR" . # 出力例: ファイル名:一致した行 # ./a.log:ERROR disk full # ./sub/b.log:ERROR timeout # -l: 一致したファイル名だけを表示 grep -rl "ERROR" . # ./a.log # ./sub/b.log
実機で確認したところ、grep -r "ERROR" .はカレントディレクトリのa.logだけでなく、サブフォルダのsub/b.logからも該当行を見つけ、./a.log:ERROR disk fullのようにファイル名付きで表示しました。-rを付けないと、ディレクトリを指定しても中身までは検索されません。「フォルダの中を全部探したのに見つからない」というときは、-rを付けているか確認してください。-l(小文字のエル)を付けると、一致した行ではなく一致したファイル名だけが表示されるので、「どのファイルにキーワードが含まれるか」をざっと知りたいときに便利です。特定の拡張子だけを対象にしたいときは、grep -r "ERROR" --include="*.log" .のように--includeで絞り込めます。
パターンは正規表現(-Fで固定文字列)
重要な注意点です。grepの検索パターンは正規表現として解釈されます。たとえば.(ドット)は「任意の1文字」を意味するため、a.bで検索するとaXbのような文字列にもヒットします。記号を文字どおりに検索したいときは-F(固定文字列)を使います。
# パターンは正規表現。. は「任意の1文字」になる grep "a.b" file.txt # → "a.b" だけでなく "aXb" や "a1b" にもヒットする # -F: 文字どおり "a.b" を探す(固定文字列・記号をそのまま扱う) grep -F "a.b" file.txt # → 文字どおりの "a.b" だけにヒット # IPアドレスやバージョン番号など記号を含む検索は -F が安全 grep -F "192.168.1.1" access.log
実機で確認したところ、a.bとaXbの2行があるファイルに対して、通常のgrep "a.b"は両方ともヒットしました(.が任意の1文字としてXに一致)。一方、grep -F "a.b"はa.bの行だけにヒットしました。IPアドレス(192.168.1.1)やバージョン番号、ファイルパスなど、.や*・[などの記号を含む文字列をそのまま検索したいときは、-Fを使うと意図しないヒットを防げます(fgrepという別名コマンドも同じ働きです)。逆に、正規表現のパターンマッチを活かしたいときは-Fを付けずに使います。
-o / -w / -E(一致部分・単語・拡張正規表現)
さらに便利なオプションです。-oは一致した部分だけを表示、-wは単語単位で一致、-Eは拡張正規表現(+や?などをそのまま使える)を有効にします。
# -o: 一致した部分だけを抜き出す(数字だけ取り出す、など) echo "price 3.14 yen" | grep -o "[0-9.]*" # 3.14 # -w: 単語単位で一致(cat は一致、category は不一致) grep -w "cat" file.txt # -E: 拡張正規表現(+ ? | () などをそのまま使える) grep -E "foo[0-9]+" file.txt # foo1, foo22 などにヒット grep -E "error|warning" app.log # error または warning
実機でも、-o "[0-9.]*"でprice 3.14 yenから3.14だけを抜き出せ、-w "cat"はcatに一致しcategoryには一致しませんでした。-Eを使うとfoo[0-9]+(fooの後に数字が1個以上)やerror|warning(どちらか)といった拡張正規表現がそのまま書けます。-Eを付けないと+や|はそのままの文字として扱われるため、複雑なパターンでは-Eを付けるのが便利です(egrepという別名でも同じです)。
パイプと組み合わせる
grepがもっとも活躍するのが、ほかのコマンドの出力を絞り込む使い方です。|(パイプ)でコマンドの出力をgrepに渡します。
# 実行中のプロセスから特定のものを探す ps aux | grep nginx # ファイル一覧から特定の拡張子を探す ls -l | grep ".log" # コマンド履歴から git を含むものを探す history | grep git # 複数の grep をつなげて絞り込む(AND検索のように) grep "ERROR" app.log | grep "disk"
ps aux | grep nginxのように、コマンドの出力を|でgrepに渡すと、必要な行だけに絞り込めます。Linuxでは「コマンドの出力をgrepで絞る」のが非常によく使われるパターンです。grep ... | grep ...とつなげれば、両方の条件を満たす行(AND検索のような絞り込み)もできます。ログ調査やプロセス確認で、日常的に使うテクニックです。
【実測】grepはどれくらい速いのか
「-Fのほうが速い」「正規表現は遅い」と言われますが、実際はどうなのか。159MB・300万行のファイルで、全行を走査する-cを付けて実測しました(WSL2のDebian・キャッシュ済み)。
| 検索方法 | 実測時間 |
|---|---|
-F 固定文字列 |
41ms |
正規表現(単純: value=500) |
43ms |
-i 大文字小文字無視 |
54ms |
-E 複雑(val.*=[0-9]+00) |
279ms |
-o 全数字の抽出(900万個) |
2,318ms |
実測の結果、単純なパターンでは-F(41ms)と正規表現(43ms)の差は誤差レベルでした。GNU grepは正規表現でも十分に最適化されているため、-Fを使う理由は「速度」ではなく「記号を文字どおり扱う安全性」と考えるのが正確です。一方、.*や+を含む複雑なパターンは約6.5倍、-oでの大量抽出は50倍以上と、確かに重くなります。もう1つ面白い発見として、grep パターン file > /dev/nullと出力を捨てた場合はわずか1msで返ってきました。GNU grepは出力先が/dev/nullだと最初のマッチで走査を打ち切るためです。「含まれているかだけ知りたい」ときは、この挙動に頼るよりgrep -q(quiet・終了コードで判定)を使うのが明示的で確実です。
実戦レシピ(ログ調査)
ここまでのオプションを組み合わせた、実務でそのまま使えるログ調査のレシピです。いずれも実機で動作を確認しています。
# 時間帯別のERROR件数を集計(何時に障害が集中したか)
grep ERROR app.log | awk '{print $1}' | cut -d: -f1 | sort | uniq -c
# 2 10 ← 10時台に2件
# 1 11 ← 11時台に1件
# ヒット行の前後1行も表示(エラーの文脈を見る)
grep -A1 -B1 "ERROR" app.log
# AND検索(ERROR かつ disk を含む行)
grep "ERROR" app.log | grep "disk"
# 存在チェック(スクリプト内で。-q は出力せず終了コードのみ)
if grep -q "ERROR" app.log; then
echo "エラーあり"
fi
実機でも、時間帯別集計は10時台2件・11時台1件と正しく集計され、-A1 -B1でヒット行の前後が表示されました。-qは結果を表示せず終了コード(見つかれば0・無ければ1)だけを返すため、ifとの組み合わせに最適です(grepは一致なしのとき終了コード1を返すことも実機で確認済みです)。awkやsort | uniq -cとつなぐこの形は、ログ調査の定番パターンとして丸ごと覚える価値があります。
主なオプション一覧
grepでよく使うオプションをまとめます。
| オプション | 働き |
|---|---|
-i |
大文字小文字を無視する |
-n |
行番号を表示する |
-v |
一致しない行を表示する |
-c |
一致した行数を数える |
-r |
サブフォルダも再帰的に検索 |
-l |
一致したファイル名だけ表示 |
-o |
一致した部分だけ表示 |
-w |
単語単位で一致 |
-E / -F |
拡張正規表現 / 固定文字列 |
よくある失敗
サブフォルダが検索されない
-rを付けないと再帰検索されません。grep -r "語" .とします。
記号を含む検索でヒットしすぎる
パターンは正規表現です。記号を文字どおり探すなら-Fを使います。
検索文字列をクォートで囲まない
スペースや記号を含むとうまく動きません。"..."で囲みます。
大文字小文字で見つからない
区別したくないときは-iを付けます。
+ や | がそのままの文字として扱われる
拡張正規表現には-Eが必要です。付けないと記号がそのままの意味になります。
エラーメッセージ逆引き
grepで実際に遭遇するエラーと原因・対処です(いずれも実機で再現したものです)。
grep: xxx: No such file or directory
指定したファイルが存在しません。ファイル名のタイプミスや、カレントディレクトリの違いを確認します。
grep: xxx: Is a directory
ファイルではなくディレクトリを指定しています。中のファイルを検索したいなら-rを付けてgrep -r "語" ディレクトリとします。
grep: xxx: Permission denied
そのファイルを読む権限がありません。パーミッションを確認するか、必要な権限で実行します。-r検索でこのエラーが大量に出て邪魔なときは、2>/dev/nullでエラーだけ非表示にできます。
grep: xxx: binary file matches
バイナリファイル(画像や実行ファイルなど)にパターンが含まれています。行を表示する代わりにこのメッセージが出ます。中身をテキストとして無理やり表示したいときは-a、バイナリを検索対象から外したいときは-I(大文字のアイ)を付けます。
よくある質問
grep "検索文字列" ファイル名で、その文字列を含む行が表示されます。複数ファイルはgrep "語" *.log、サブフォルダも含めるならgrep -r "語" .とします。大文字小文字を無視するなら-iを付けます。-r(再帰)オプションを付けます。grep -r "検索語" ディレクトリで、その中のすべてのファイルを検索します。一致したファイル名だけを知りたいときは-l、特定の拡張子だけなら--include="*.log"を併用します。grepのパターンは正規表現なので、.や*は特別な意味を持ちます。文字どおりに検索したいときは-F(固定文字列)を付けてください。IPアドレスやバージョン番号など、記号を含む文字列の検索では-Fが安全です。-vオプションを使います。grep -v "DEBUG" app.logで、DEBUGを含まない行だけが表示されます。特定のノイズ行を除いて中身を確認したいときに便利です。|(パイプ)でgrepに渡します。ps aux | grep nginxのように書くと、コマンドの出力から必要な行だけを抜き出せます。grep ... | grep ...とつなげれば、複数条件での絞り込みもできます。まとめ
- 基本は
grep "検索文字列" ファイル名。一致する行を表示します。 -i(大小無視)・-n(行番号)・-v(否定)・-c(件数)が定番です。- サブフォルダは
-rで再帰検索します。 - パターンは正規表現。記号を文字どおり探すなら
-Fを使います。 コマンド | grep ...で、出力の絞り込みに大活躍します。
grepは、Linuxでもっともよく使うコマンドの1つです。「-rで再帰」「記号は-Fで固定文字列」の2点を押さえ、パイプと組み合わせれば、ログ調査やファイル検索を効率よくこなせます。まずは基本の検索から始めて、少しずつオプションを使いこなしていきましょう。
- grep(文字列検索)
- find(ファイル検索)
- sed(置換・行編集)
- awk(列抽出・集計)
- cut(列の切り出し)
- chmod(パーミッション)
- tar(圧縮・解凍)
- gzip・gunzip(ファイル圧縮)
- リダイレクトとパイプ
- echo・printf(文字列出力)
- ps・kill(プロセス管理)
- free・uptime(メモリ/負荷)
- top(リアルタイム監視)
- 環境変数とPATH
- which・type(コマンドの正体)
- ln(シンボリックリンク)
- cp・mv・rm(コピー/移動/削除)
- touch・mkdir(ファイル/フォルダ作成)
- basename・dirname(パス分解)
- history(コマンド履歴)
- curl(HTTP通信・API)
- wget(ダウンロード)
- ping(疎通確認)
- dig・nslookup(DNS調査)
- ss・netstat(ポート確認)
- jq(JSON処理)
- vim(基本操作・終了方法)
- cron・crontab(定期実行)
- test・[ ](条件判定)
- read(入力の読み取り)
- date(日付・時刻)
- sort・uniq・wc(並べ替え/集計)
- xargs(一括処理)
- chown・chgrp(所有者/グループ変更)
- diff(ファイル比較)
- du・df(ディスク使用量)
- head・tail(先頭/末尾・ログ監視)
- cat・less(ファイル表示)
- alias(コマンドの別名)
- nohup(SSH切断対策)
- tmux(セッション管理)
- よく使うコマンドまとめ
- cd(ディレクトリ移動)

