こんにちは、かつコーチです。
前回は、cat・less・head・tailを使ったファイルの中身の確認方法を解説しました。
今回は、テキスト処理の中でも特に使用頻度が高いgrepコマンドを解説します。
数千行のログファイルから、目的のエラーメッセージを一瞬で見つけ出せるのがgrepの強みです。
この記事を読めば、基本的な検索から正規表現を使った応用検索まで扱えるようになります。
grepとは?
指定した文字列を含む行を抜き出すコマンド
grep(Global Regular Expression Print)は、ファイルの中から指定した文字列(パターン)を含む行だけを抜き出して表示するコマンドです。
# ファイル内で"error"を含む行を検索する
grep "error" /var/log/syslog
前回の記事で紹介したhead・tailが「位置」でファイルの一部を抜き出すのに対し、grepは「内容」で該当する行を抜き出す点が大きな違いです。
サーバー運用でエラーの原因を調査する際、この違いを理解しておくと、状況に応じて適切なコマンドを選べるようになります。
パイプと組み合わせて真価を発揮する
grepは単体でも使えますが、他のコマンドの出力結果を受け取って絞り込む使い方が特に強力です。
# 実行中のプロセス一覧から、nginxに関する行だけを抜き出す
ps aux | grep nginx
前回解説したパイプ(|)を使うことで、psコマンドの大量の出力から、必要な情報だけを瞬時に絞り込めます。
grepの基本オプションを使いこなす
よく使うオプション一覧
| オプション | 意味 |
|---|---|
-i | 大文字・小文字を区別せずに検索する |
-v | 指定した文字列を含まない行を表示する(逆マッチ) |
-n | マッチした行の行番号も一緒に表示する |
-r | ディレクトリ配下を再帰的に検索する |
-c | マッチした行数だけをカウントして表示する |
これらは単体でも、組み合わせても使えます。
# 大文字小文字を区別せず、行番号付きで検索する
grep -in "error" /var/log/syslog
除外検索(-v)で不要な行を取り除く
意外と実務で使う頻度が高いのが、-vによる除外検索です。
# "DEBUG"を含まない行だけを表示する(DEBUGログを除外)
grep -v "DEBUG" /var/log/app.log
ログの大半がDEBUGレベルの出力で埋まっている場合、-vで除外してから読むと、重要な行だけに集中できます。
再帰検索(-r)でディレクトリ全体を対象にする
複数のファイルにまたがってコードや設定を検索したい場合は、-rオプションが便利です。
# カレントディレクトリ配下のファイルを再帰的に検索する
grep -r "database_host" /etc/myapp/
設定ファイルが複数のディレクトリに分散している場合でも、-rを使えば1つのコマンドで一括検索できます。
ファイル名も一緒に知りたい場合は、-nと組み合わせて、どのファイルの何行目にマッチしたかまで把握できます。
# ファイル名・行番号付きで再帰検索する
grep -rn "database_host" /etc/myapp/
正規表現で柔軟に検索する
正規表現とは
正規表現とは、文字列のパターンを表現するための記法のことで、「〇〇で始まる」「数字が続く」といった条件を柔軟に指定できます。
grepは正規表現に対応しており、単純な文字列一致だけでなく、パターンによる検索が可能です。
# 行頭が"Error"で始まる行だけを検索する
grep "^Error" /var/log/app.log
# 行末が".log"で終わる行を検索する
grep "\.log$" file_list.txt
^は行頭、$は行末を表す記号で、検索したい位置を明示的に指定できます。
よく使う正規表現の記号
| 記号 | 意味 |
|---|---|
^ | 行頭 |
$ | 行末 |
. | 任意の1文字 |
* | 直前の文字の0回以上の繰り返し |
[0-9] | 0〜9のいずれか1文字(数字) |
# IPアドレスらしき数字の並びを含む行を大まかに検索する
grep "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" /var/log/nginx/access.log
正規表現は奥が深いテーマのため、最初から完璧に覚える必要はなく、^と$、[0-9]あたりから少しずつ慣れていくのがおすすめです。
つまずきやすいポイント:特殊文字をエスケープせずに検索がヒットしなかった話
私が本番環境のログを調査していた際、IPアドレスで検索したのに1件もヒットしないという経験をしたことがあります。
❌ Before:正規表現の特殊文字をそのまま使ってしまう
# ドット(.)を「任意の1文字」として解釈されてしまう
grep "192.168.1.1" /var/log/nginx/access.log
一見正しく見えるこのコマンドですが、.(ドット)は正規表現において「任意の1文字」を意味する特殊文字です。
そのため192a168c1d1のような文字列にも本来はマッチしてしまう、意図とは異なる検索になっていました。
このときは検索結果が0件だったため気づけましたが、たまたま似た文字列がログに存在していたら、誤った行まで拾ってしまうところでした。
✅ After:固定文字列検索(-F)を使うか、特殊文字をエスケープする
# -Fオプションで正規表現を無効化し、文字列そのものとして検索する
grep -F "192.168.1.1" /var/log/nginx/access.log
# または、ドットをエスケープして「ドットそのもの」として扱う
grep "192\.168\.1\.1" /var/log/nginx/access.log
-F(Fixed strings)オプションを付けると、正規表現を使わず、入力した文字列をそのまま検索対象にできます。
IPアドレスやバージョン番号のように「.」を含む固定文字列を検索するときは、-Fを使うか\.でエスケープするのが安全だと、このときに学びました。
応用・一歩先の使い方
grepとsedを組み合わせた実践例
grepで該当行を確認し、問題なければ次回解説するsedで置換する、という流れは実務でよく使われるパターンです。
# まずgrepで対象行を確認する
grep "old-domain.com" /etc/nginx/sites-available/default
# 問題なければsedで置換する(sedは次回詳しく解説)
sudo sed -i 's/old-domain.com/new-domain.com/g' /etc/nginx/sites-available/default
いきなり置換せず、まずgrepで「どこが対象になるか」を確認してから作業する流れを習慣にすると、意図しない置換事故を防げます。
拡張正規表現(-E)でより複雑なパターンを扱う
複数の候補をまとめて検索したい場合は、-Eオプションで拡張正規表現を使うと表現力が上がります。
# "error"または"warning"を含む行を検索する
grep -E "error|warning" /var/log/app.log
|(パイプ記号)は正規表現の中では「または」を意味し、複数のキーワードをまとめて検索する際に便利です。
まとめ
この記事のポイント
grepは指定した文字列(パターン)を含む行を抜き出すコマンドで、パイプと組み合わせると特に強力-i(大文字小文字無視)、-v(除外)、-r(再帰検索)、-n(行番号表示)はセットで覚えておくと便利- 正規表現の
^(行頭)・$(行末)・.(任意の1文字)を理解すると柔軟な検索ができる - ドットなどの特殊文字を含む固定文字列を検索するときは
-Fオプションかエスケープ(\.)を使う
次に読むべき記事
検索の基本が分かったら、次はファイルの中身を置換するsedコマンドに進みましょう。
→ 次の記事:sedで文字列を置換する基本
タグ: Linux, 中級者向け, テキスト処理