【Linux】grepコマンドの使い方|システム開発でよく使うオプションまとめ

Linux

Linux環境でのシステム開発業務において、
ログファイルやソースコードなど、ファイルの中から特定の文字列を検索したい場面がよくあります。

そのようなときに便利なのが、grep コマンドです。

  • ログファイルからエラーメッセージや関数名を検索する
  • ソースコードから関数名や変数名を検索する

といったことができるため、作業の効率化には欠かせないコマンドの一つです。

筆者もシステム開発業務中において、ログファイルから修正した処理をトレースする際に、
関数名やログメッセージをキーワードに grep コマンドで抽出することで、
数万行とある膨大なログの見るべき箇所の特定にかかる時間を短縮しています。

ただ、grep コマンドも他のコマンドと同じく様々なオプションがあり、
用途によって使い分ける必要があります。

かけりゅー
かけりゅー

本記事では、grepコマンドの基本的な使い方から、
開発業務でよく使うオプションまでを具体例とセットでまとめています。

grepコマンドとは

grep コマンドは、ファイル内に含まれる特定の文字列を検索するコマンドです。

ログファイルやソースコードなど、
大量のファイルの中から必要な情報を素早く見つけたいときに使用します。

コマンドの基本構文は以下のとおりです。

grep [OPTION] "検索文字列" [検索対象ファイル名]

オプションを指定することで、用途に応じた検索方法で文字列の検索を行います。
システム開発で使用頻度の高い各オプションについては、後述で詳しくまとめています。

grepコマンドの基本的な使い方

システム開発業務において、特に使用頻度の高い使い方を紹介します。

また、本項で紹介する実行例では、
次の内容の food/fruits.txt 、もしくは food/data/food.csv を使用します。

$ cat food/fruits.txt
Apple
apple
Pineapple
banana
GRAPE
grape
grapefruit
Orange

$ cat food/data/food.csv
name,category
tomato,vegetable
eggplant,vegetable
chicken,meat
beef,meat
apple,fruit
grape,fruit

特定の文字列を検索する

オプション指定なしの場合、指定した文字列を検索します。

$ grep "grape" food/fruits.txt
grape
grapefruit

fruits.txt というファイル中から “grape” の文字列を含む行を検索し、出力します。
大文字・小文字は区別されるため、”GRAPE” は検索でヒットしません。

大文字・小文字を区別せず検索する

検索文字列の大文字・小文字を区別せずに文字列を検索します。

$ grep -i "grape" food/fruits.txt
GRAPE
grape
grapefruit

-i を付けない場合は “grape”、”grapefruit” の2件が検索でヒットしますが、
-i を付けることで大文字・小文字を区別せずに検索されるため、
“GRAPE” のように表記が異なる行も合わせてヒットします。

検索箇所の前後の行も表示する

指定した文字列だけではなく、その前後数行の内容も表示したい場合に、
-A-B-C オプションを付与することで、検索結果の前後の行も合わせて表示できます。

オプション出力内容
-A指定した行数だけ、一致した行の後ろも表示する
-B指定した行数だけ、一致した行の前表示する
-C指定した行数だけ、一致した行の前後を表示する
$ grep -C 1 "banana" food/fruits.txt
Pineapple
banana
GRAPE

行番号付きで検索する

指定した検索文字列が含まれる場所(行数)も合わせて知りたい場合、
-n オプションを付与することで、検索文字列が含まれる行数も合わせて出力されます。

$ grep -n "grape" food/fruits.txt
6:grape
7:grapefruit

指定した文字列を含まない行を検索する

検索文字列を含まない行だけを抽出したい場合、
-v オプションを付与することで、指定した文字列を含まない行のみを検索できます。

$ grep -v "apple" food/fruits.txt
Apple
banana
GRAPE
grape
grapefruit
Orange

“apple” を含む行が除外され、それ以外の行のみが出力されます。

一致した件数だけを確認する

検索結果の内容ではなく、一致した件数だけを知りたい場合、
-c オプションを付与することで、一致した件数のみを出力できます。

$ grep -c "grape" food/fruits.txt
2

単語単位で検索する

検索文字列を単語単位で検索したい場合、
-w オプションを付与することで、部分一致を除外した単語単位の検索ができます。

$ grep -w "grape" food/fruits.txt
grape

-w を付けない場合、”grapefruit” のように grape を含む別の単語もヒットしますが、
-w を付けることで “grape” という単語単体に一致する行のみに絞り込めます。

サブディレクトリも含めて検索する

検索対象としたいファイルがサブディレクトリなど複数のディレクトリに存在する場合、
-r オプションを付与することで、指定したディレクトリ配下を再帰的に検索します。

$ grep -r "grape" food    //★コードブロック
food/fruits.txt:grape
food/fruits.txt:grapefruit
food/data/food.csv:grape,fruit

このように、food配下のサブディレクトリやファイル形式を問わず、一括で検索対象にできます。

一致したファイル名だけを確認する

複数ファイルを検索対象とし、どのファイルに一致する行があったかだけを知りたい場合、
-l オプションを付与することで、一致したファイル名のみを出力できます。

$ grep -rl "grape" food
food/fruits.txt
food/data/food.csv

大量のログファイルの中から、まず対象ファイルを絞り込みたいときに使用します。

特定のファイルだけを対象に検索する

検索対象を特定のファイルだけに絞りたい場合、
--include オプションを付与することで、指定したファイル名や拡張子のファイルのみを検索できます。

$ grep -r --include="*.txt" "grape" food
food/fruits.txt:grape
food/fruits.txt:grapefruit

.csv など .txt 以外のファイルが対象から除外され、.txt ファイルのみが検索されます

特定のファイルを除外して検索する

特定のファイルを検索対象から除外したい場合、
--exclude オプションを付与することで、
指定したファイル名や拡張子のファイルを検索対象から除外して検索できます。

$ grep -r --exclude="*.txt" "grape" food
food/data/food.csv:grape,fruit

.txt ファイル以外の形式のファイルを対象に “grape” が含まれる箇所を検索します。

正規表現で検索する

正規表現を利用することで、指定した条件に一致する文字列を柔軟に検索できます。

$ grep -E "GRAPE|Orange" food/fruits.txt
GRAPE
Orange

上記の場合、”GRAPE” または “Orange” を含む行を検索します。

大文字・小文字は区別されるため、
このケースでは “grape” や “grapefruit” はヒットしません。

-E は拡張正規表現(ERE)を有効にするオプションです。
POSIX仕様でも定義されています。
関連情報:POSIX grep specification

正規表現の特殊文字(. や * など)をそのまま検索する

正規表現の特殊文字(. や * など)を含む文字列をそのまま検索したい場合、
-F オプションを付与することで、検索文字列を正規表現として解釈せず、
文字列そのものとして検索できます。

たとえば、以下のような設定ファイルからIPアドレス “192.168.1.1” を検索する場合を考えます。

$ cat network.conf
server_ip=192.168.1.1
hostname=ip-192-168-1-1.ec2.internal
$ grep "192.168.1.1" network.conf
server_ip=192.168.1.1
hostname=ip-192-168-1-1.ec2.internal

“.” は正規表現では「任意の1文字」を意味するため
IPアドレスの区切りにハイフンを使うAWSのEC2ホスト名のような、
無関係な行まで意図せずヒットしてしまいます。

$ grep -F "192.168.1.1" network.conf
server_ip=192.168.1.1

-F を付けることで “.” を文字通りのピリオドとして扱うため、意図した行のみに絞り込めます。

筆者も実務で、ログファイル内のIPアドレスを検索文字列に含めた際、
ピリオドが正規表現として解釈されてしまい、
無関係な文字列を含む行までヒットしてしまった経験があります。

記号を含む文字列を検索する際は、
-F を付けることで意図しない一致を防げます。

grepコマンドの実用例

ソースコードから関数の実装箇所を探す

設計書などで関数名だけが判明しているときに、
ソースコード全体から関数の実装箇所や使用箇所を抽出できます。

$ grep -rn "checkCollision" ./src
./src/collision.c:42:int checkCollision(Player *player, Enemy *enemy)
./src/game.c:128:if (checkCollision(&player, &enemy)) {
./src/battle.c:85:result = checkCollision(player, boss);
./src/debug.c:23:printf("%d\n", checkCollision(&player, &enemy));
./src/test/collision_test.c:14:assert(checkCollision(&mockPlayer, &mockEnemy) == true);
./src/test/collision_test.c:22:assert(checkCollision(&mockPlayer, &mockEnemy) == false);

このようにgrep検索を実行することで、
checkCollision() の実装箇所と呼び出し箇所をまとめて確認することができます。

かけりゅー
かけりゅー

ソースファイルなど複数のファイルに対して検索するときに便利なため、
このオプションは筆者もよく使用しています。

特定のファイルを除外して関数の呼び出し箇所を探す

テストコードやモックが混在するリポジトリで関数の呼び出し箇所を探すと、
先ほどの checkCollision の検索結果のように、本来確認したい本番コードの呼び出し箇所に、
テストコードも混ざって出力されてしまうことがあります。

そのようなとき、-v と組み合わせることでテストコードを除外して検索できます。

$ grep -rn "checkCollision" ./src | grep -v "test"
./src/collision.c:42:int checkCollision(Player *player, Enemy *enemy)
./src/game.c:128:if (checkCollision(&player, &enemy)) {
./src/battle.c:85:result = checkCollision(player, boss);
./src/debug.c:23:printf("%d\n", checkCollision(&player, &enemy));

このように、パスに “test” を含む行を除外することで、
本番コード側の呼び出し箇所のみに絞り込んで確認できます。

ソースコードからフラグ変数の前後にある処理を確認したい

フラグ変数の前後にある処理をパッと確認したいときに、それらも含めて検索できます。

$ grep -C 3 "isLogin" UserService.c
if (user == NULL) {
    return ERROR;
}
isLogin = true;
updateLoginHistory(user);
sendNotification(user);
writeAuditLog(user);

このようにgrep検索を実行することで、
フラグ変数の使用箇所前後で実行される処理を確認することができます。

コマンドの出力結果から必要な情報のみを抽出する

grep は単体でファイルを検索するだけでなく、
パイプ(|)を使って他のコマンドの出力結果に対して検索することもできます。

$ history | grep ip
220  ip a
245  ip route
256  history | grep ip

historyコマンドと組み合わせて使用した場合、
過去に実行したコマンドの中から特定の文字列を含むものだけを絞り込んで表示できます。

また、リアルタイムで出力され続けるログを監視しながら、
特定の文字列が出力された行だけを確認したい場合は、
tail -f と組み合わせて使用します。

$ tail -f access.log | grep "ERROR"

アプリケーションの動作確認中に、エラーが発生した瞬間を見逃さず確認したいときに使用します。

tailコマンドの詳しい使い方については、次の記事で詳しくまとめています。
【Linux】tailコマンドの使い方|リアルタイムでログを監視する方法

このように、出力内容のうち、特定の情報のみを確認したい場合に、
パイプを使って grep コマンドと組み合わせることで、必要な情報のみを抽出することができます。

まとめ

grepコマンドは、ファイルやコマンド出力の中から特定の文字列を検索するためのコマンドです。
オプションを使い分けることで用途に応じて検索条件を柔軟に調整できます。

システム開発業務では主に以下のような用途で使用します。

  • ソースコードから関数名や変数名をもとに処理の実装箇所を検索する
  • ログファイルからエラーや特定の出力を探す
  • 他のコマンドと組み合わせることで、コマンドの出力結果を絞り込む
かけりゅー
かけりゅー

grepコマンドによる文字列検索は、システム開発業務でもよく使うため、
覚えておけば役に立つこと間違いなしです。

一方で、本記事で紹介した文字列の検索だけでなく、
ファイルやディレクトリそのものを検索する find コマンドも、
設定ファイルの確認などで活用する機会が多いコマンドです。

find コマンドについても詳しく知りたい方は、以下の記事も参考にしてみてください。
【Linux】findコマンドでファイルを検索する方法|作業効率向上

参考リンク

GNU grep 日本語マニュアル:grepコマンド

コメント