正規表現 - 基本・拡張正規表現とgrep応用

正規表現 - 基本・拡張正規表現とgrep応用

この記事で達成できること

  • 基本正規表現(BRE)と拡張正規表現(ERE)の違いを説明できる
  • アンカー・文字クラス・量指定子を使ったパターンを正確に書ける
  • grep / egrep / sed で正規表現を使い分けられる
  • ログから特定パターンの行を抽出・除外できる
  • 試験で頻出の「BRE のバックスラッシュ要否」を間違えなくなる

LPIC-1 主題 103.7「正規表現を使用してテキストファイルを検索する」の中核。正規表現は文字列のパターンを記述する言語で、grep / sed / awk すべての基盤になる。

BRE と ERE の判断

正規表現には方言がある。LPIC で問われるのは POSIX の 2 種。

種類 使うコマンド + ? { } ( ) | の扱い
基本正規表現 BRE grep / sed バックスラッシュが必要(\+ \{ \(
拡張正規表現 ERE grep -E / egrep / sed -E そのまま使える(+ { (

grep\{3\} と書くのに grep -E では {3}」という差は試験頻出。どちらの方言で書いているかを常に意識する。

メタ文字一覧

メタ文字 意味
. 任意の1文字 a.c → abc, axc
* 直前要素の0回以上 ab* → a, ab, abb
^ 行頭アンカー ^root
$ 行末アンカー bash$
[ ] 文字クラス [0-9] 数字1文字
[^ ] 否定文字クラス [^0-9] 数字以外
\+(ERE は + 直前要素の1回以上 a\+
\?(ERE は ? 直前要素の0または1回 colou\?r
\{n,m\}(ERE は {n,m} n回以上m回以下 [0-9]\{1,3\}
|(OR / 選択) いずれかにマッチ。BRE はバックスラッシュ必須、ERE は不要 cat|dog

手順

Step 1: アンカーで位置を固定する

grep '^#' /etc/ssh/sshd_config
grep 'bash$' /etc/passwd
grep -x 'root' users.txt
#	$OpenBSD: sshd_config
#Port 22
root:x:0:0:root:/root:/bin/bash
root

^ は行頭、$ は行末を表すゼロ幅アンカー。grep -x は行全体一致(^pattern$ と等価)。コメント行抽出や完全一致検索の基本。

Step 2: 文字クラスで範囲を指定する

grep '[0-9]\{1,3\}\.[0-9]\{1,3\}' access.log
grep -E '[0-9]{1,3}(\.[0-9]{1,3}){3}' access.log
grep '[[:space:]]' config.txt
192.168.1.10 - - [17/May/2026]
10.0.0.5 - - [17/May/2026]

[0-9] は数字 1 文字、\{1,3\} は 1〜3 回の繰り返し(BRE はバックスラッシュ必須)。[[:space:]] は POSIX 文字クラスで空白類にマッチする。

Step 3: BRE と ERE を使い分ける

grep 'colou\?r' notes.txt
grep -E 'colou?r' notes.txt
grep -E 'error|warning|fatal' app.log
color theme
favourite colour
[ERROR] disk full
[WARNING] high load

? + | {} () を使うときは grep -E(ERE)が読みやすい。BRE で同じことをするにはバックスラッシュエスケープが必要になり可読性が落ちる。

Step 4: 抽出と除外を組み合わせる

grep -v '^#' /etc/fstab | grep -v '^$'
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' access.log | sort -u
grep -ci 'timeout' app.log
UUID=xxxx / ext4 defaults 0 1
192.168.1.10
10.0.0.5
7

-v でマッチしない行(コメント・空行除去)、-o でマッチ部分のみ抽出、-c で件数、-i で大文字小文字無視。設定ファイルの実効行抽出に頻出。

Step 5: sed で正規表現置換する

echo "2026-05-17" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
sed -n '/^ERROR/p' app.log
17/05/2026
ERROR connection refused

sed -E は ERE モード。\1 \2 は後方参照で、( ) でキャプチャしたグループを置換側で再利用する。日付フォーマット変換などに使う。

なぜ BRE にバックスラッシュが要るのか

BRE は歴史的に古い grep / ed の構文を保つために、+ ? { ( | を「特殊な意味なし(リテラル)」として扱う。これらを量指定子・グループ・OR として使うにはバックスラッシュで「これはメタ文字」と明示する必要がある。ERE はこの煩雑さを解消し、特殊文字を最初からメタ文字として扱う新しい構文。grep -E / egrep が ERE を有効化する。

この設計差を理解していないと「grep 'a+'a の 1 回以上にマッチしない(リテラルの a+ を探す)」という挙動を説明できない。LPIC ではこの落とし穴がそのまま出題される。

トラブルシューティング

症状: grep 'a+' が1回以上にマッチしない

原因: BRE では + がリテラル文字扱い

確認:

grep 'a\+' file
grep -E 'a+' file

対処: ERE(grep -E)を使うか、BRE なら \+ とエスケープする。

症状: ドットが任意の文字にマッチして誤検出する

原因: . は正規表現で任意の1文字を意味する

確認:

grep '192\.168' access.log

対処: リテラルのドットを探すときは \. とエスケープする。固定文字列検索なら grep -F(fgrep)が安全。

症状: 特殊文字を含む文字列を検索できない

原因: [ * $ などがメタ文字として解釈される

確認:

grep -F '[error]' app.log

対処: パターンに正規表現が不要なら grep -F で固定文字列検索する。必要な箇所だけ \ でエスケープする。

作業完了チェックリスト

  • [ ] ^ $ アンカーで行頭・行末一致を確認した
  • [ ] [0-9] 等の文字クラスと量指定子を組み合わせた
  • [ ] BRE(\{3\})と ERE(grep -E '{3}')の差を実機で確認した
  • [ ] -v -o -c -i の各オプションを試した
  • [ ] sed -E の後方参照(\1)で置換した

まとめ

場面 書き方 目的
行頭一致 grep '^pattern' コメント/特定行抽出
完全一致 grep -x / ^...$ 行全体一致
1回以上 grep -E 'a+' 連続文字検出
抽出のみ grep -o マッチ部分だけ取得
置換 sed -E 's/.../.../' 後方参照で整形

正規表現は grep / sed / awk すべての基盤。次はリンク機構やプロセス優先度など他の試験範囲に進むと知識が連結する。

次に読む