Linux: テキスト検索 — grepと正規表現

数千のファイルの中からあの1行を見つける — それがgrepの得意分野です。おそらくLinuxで最も頻繁に使われるコマンドでしょう。

📋 前提条件:まず以下を完了していること

1. このレッスンで学ぶこと


2. 100ファイルの中からコードを見つけるストーリー

(1) 悩み:API名を変更したいが、どのファイルが使っているか不明

小明はPythonファイル内のrequests.getの呼び出しをすべてhttpx.getに変更する必要がありました。プロジェクトには100以上のファイルがあり — 1つずつ開くのは不可能でした。

(2) grep再帰検索

BASH
grep -rn "requests\.get" --include="*.py" src/

出力:

TEXT
src/api/client.py:15: response = requests.get(url, headers=headers)
src/api/users.py:42: data = requests.get(f"{API_URL}/users")
src/api/orders.py:78: result = requests.get(ORDER_URL)

3ファイルに呼び出しがあり — 1秒未満で発見。

(3) 得られるもの:干し草の山から針を見つける正確さへ

小明は習慣を身につけました:コードを変更する前にgrep -rnで関連するすべての場所を確認し、確認してから編集を開始する。


3. 知識ポイント

(1) grepの基本的な使い方

BASH
# Basic search
grep "pattern" filename

# Common option combinations
grep -rn "TODO" src/    # Recursive search, show line numbers
grep -i "error" log.txt # Ignore case
grep -v "debug" log.txt # Invert match (lines NOT containing debug)
grep -c "failed" log.txt # Count only
grep -l "main" *.py      # Show only matching filenames
grep -A5 -B5 "exception" log.txt # Show 5 lines before and after match
オプション 意味
-i 大文字小文字を無視
-v 反転一致(非一致行を表示)
-c 一致行数のみ出力
-n 行番号を表示
-rまたは-R サブディレクトリを再帰検索
-l 一致を含むファイル名のみ表示
-L 一致を含まないファイル名のみ表示
-w 単語全体で一致
-A NUM 一致行の後NUM行を表示
-B NUM 一致行の前NUM行を表示
-C NUM 一致行の前後NUM行を表示

(2) 基本正規表現

メタ文字 意味
. 任意の1文字に一致 h.tはhit / hot / hatに一致
^ 行の先頭 ^rootはrootで始まる行に一致
$ 行の末尾 bash$はbashで終わる行に一致
* 前の文字の0回以上の繰り返し ab*cはac / abc / abbcに一致
[abc] セット内の任意の1文字 [Hh]elloはHelloまたはhelloに一致
[^abc] セットに含まれない文字 [^0-9]は数字以外の文字に一致
\< 単語の先頭 \<rootは単語の先頭のrootに一致
\> 単語の末尾 root\>は単語の末尾のrootに一致
💡 ヒント:正規表現の.は任意の1文字に一致します — リテラルのドット(IPアドレスなど)に一致させるにはバックスラッシュでエスケープする必要があります:grep "192\.168\." fileとし、grep "192.168." fileとしてはいけません(後者は192X168Yなどにも誤って一致します)。

(3) 拡張正規表現(grep -E)

基本正規表現では+?|{}()はエスケープが必要です。拡張正規表現ではこれらのメタ文字を直接使用できます(grep -Eまたはegrep経由):

ℹ️ 注意:基本と拡張正規表現の主な違いは、拡張正規表現(grep -E)では+?|{}()をバックスラッシュエスケープなしで使用できる点です。基本正規表現ではgrep "error\|warning"のように|をエスケープする必要がありますが、grep -E "error|warning"では不要です。より読みやすいgrep -Eを推奨します。

メタ文字 意味
+ 前の文字の1回以上の繰り返し ab+cはabc / abbcに一致、acには不一致
? 前の文字が0回または1回 colou?rはcolorまたはcolourに一致
` ` または
{n,m} n回からm回の繰り返し [0-9]{3,5}は3〜5桁の数字に一致
() グループ化 `(error

(4) ▶ サンプル:基本検索

BASH
# Search in a file
grep "root" /etc/passwd
# root:x:0:0:root:/root:/bin/bash

# Case-insensitive
echo -e "Error\nerror\nERROR" | grep -i "error"
# All three lines match

# Count
grep -c "nologin" /etc/passwd
# Output: 16

# Show line numbers
grep -n "www-data" /etc/passwd
# 33:www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

出力:

TEXT
root:x:0:0:root:/root:/bin/bash
Error
error
ERROR
16
33:www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

(5) ▶ サンプル:反転一致

BASH
# Exclude comment lines
grep -v "^#" /etc/ssh/sshd_config | grep -v "^$"

# Exclude debug logs
grep -v "DEBUG" app.log | grep "ERROR"

# Exclude files with certain extensions
ls -la | grep -v "\.md$"

出力:

TEXT
Port 22
PermitRootLogin no
PasswordAuthentication no
2026-07-07 10:23:45 ERROR Database connection failed
2026-07-07 10:24:12 ERROR Timeout waiting for response
drwxr-xr-x 2 alice alice 4096 Jul  7 10:00 src
-rw-r--r-- 1 alice alice 1234 Jul  7 10:00 config.yaml

(6) ▶ サンプル:再帰的コード検索

BASH
# Search for all TODO comments in the project
grep -rn "TODO\|FIXME\|HACK" --include="*.py" src/

# Search in specific file types
grep -rn "def " --include="*.py" --include="*.js" .

# Search excluding node_modules
grep -rn "api_key" --exclude-dir=node_modules --exclude-dir=.git .

# Show only filenames
grep -rl "class User" src/

出力:

TEXT
src/api/client.py:23:# TODO: Add retry logic
src/models/user.py:45:# FIXME: Handle edge case
src/utils/helpers.py:12:# HACK: Temporary workaround
src/api/client.py:10:def get_user(user_id):
src/models/user.py:5:def validate_email(email):
config/settings.py:3:api_key = "sk-xxx"
src/models/user.py
src/auth.py
💡 ヒントgrep -rnはコード検索のゴールデンコンビ — -rでディレクトリを再帰検索、-nで行番号表示、--includeでファイルタイプを制限。大規模プロジェクトでもgrep -rn "pattern" --include="*.py" src/で1秒以内にターゲットコードを特定できます。

(7) ▶ サンプル:コンテキスト表示

BASH
# Show 3 lines before and after the match
grep -C 3 "NullPointerException" app.log

# Show 5 lines after the match
grep -A 5 "Traceback" python_error.log

# Show 2 lines before the match
grep -B 2 "500" access.log

出力:

TEXT
10:23:01 INFO Processing request
10:23:02 WARN Memory usage high
10:23:03 ERROR NullPointerException at UserService.java:45
10:23:04 INFO Retrying operation
10:23:05 WARN Connection pool low
Traceback (most recent call last):
  File "app.py", line 42, in handle_request
    result = process(data)
  File "processor.py", line 15, in process
    return transform(input)
ValueError: Invalid input data
192.168.1.100 - - [07/Jul/2026:10:23:44] "POST /api/data"
192.168.1.100 - - [07/Jul/2026:10:23:45] "POST /api/data HTTP/1.1" 500 0

(8) ▶ サンプル:正規表現の実践

BASH
# Match email addresses
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" contacts.txt

# Match IP addresses
grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log

# Match URLs
grep -E "https?://[^ ]+" index.html

# Match dates (YYYY-MM-DD)
grep -E "[0-9]{4}-[0-9]{2}-[0-9]{2}" logs/*.log

# Match lines starting with a digit and ending with a letter
grep "^[0-9].*[a-zA-Z]$" file.txt

出力:

TEXT
alice@example.com
bob.smith@company.org
contact@my-site.net
192.168.1.100 - - [07/Jul/2026] ...
10.0.0.45 - - [07/Jul/2026] ...
https://example.com/api/users
http://internal.server.local/status
2026-07-07
2026-07-08
1abc
23x

(9) ▶ 総合例:ログエラー分析

BASH
#!/bin/bash
# analyze-errors.sh - Log error analysis

LOG_FILE="${1:-/var/log/syslog}"

echo "=== Error Analysis Report ==="
echo "Source file: $LOG_FILE"
echo ""

echo "1. Error count by type:"
grep -i "error" "$LOG_FILE" | awk '{print $5}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "2. Last 5 errors:"
grep -i "error" "$LOG_FILE" | tail -5

echo ""
echo "3. Critical alerts (OOM / Disk Full / Connection Refused):"
grep -iE "oom|out of memory|disk full|no space left|connection refused" "$LOG_FILE"

echo ""
echo "4. Error trend (by hour):"
grep -i "error" "$LOG_FILE" | grep -oP "\d{2}:\d{2}" | cut -d: -f1 | sort | uniq -c | sort -rn

❓ よくある質問

Q: grepと正規表現の違いは? A: grepはファイル内のパターンに一致する行を検索するコマンドラインツール、正規表現(regex)はテキストパターンを記述する構文です。grepは検索パターンとして正規表現をサポートしますが、正規表現自体はsed、awk、Pythonなど多くのツールや言語でも使える構文に過ぎません。

Q: grep -rgrep -Rは同じですか? A: 基本的には同じです。-Rはシンボリックリンクをたどりますが、-rはデフォルトでたどりません。日常使用ではどちらでも構いません。

Q: 大文字小文字を無視して検索するには? A: -iオプションを使用:grep -ir "error" /var/log/

Q: grepで中国語が検索できないのはなぜですか? A: ロケールの問題の可能性があります。中国語文字はUTF-8でマルチバイトエンコーディングされ、grepはデフォルトでバイト単位で一致させます。export LANG=zh_CN.UTF-8またはgrep -P(Perl正規表現モード)を試してください。

Q: grep -vの用途は? A: 反転一致 — パターンに一致しない行を出力します。他のgrep呼び出しと組み合わせて特定の行を「除外」できます。例:grep -v "^#"でコメント行を除外、grep -v "^$"で空行を除外。


📖 まとめ


📝 練習問題

  1. 基本(難易度 ⭐)/etc/passwdでログインシェルが/bin/bashのユーザーを検索し、ログファイルのエラーを検索して-cでカウントする
  2. 中級(難易度 ⭐⭐):プロジェクトディレクトリを再帰検索してすべてのFIXMEとTODOコメントを見つけ、grep -vで.gitディレクトリを除外し、総コード行数をカウントする
  3. 上級(難易度 ⭐⭐⭐):正規表現でログファイル内の全IPアドレスに一致させ、sortuniq -cを組み合わせてIP別出現回数をカウントし、最頻出IPトップ10を見つける
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%