LPIC Level1 復習ラジオ 19:ワイルドカードと正規表現

投稿日:2026-07-11

音声

※ AI音声で読み上げます

目次

  1. ワイルドカードと正規表現の違い
  2. *によるファイル名展開
  3. ?による1文字の指定
  4. []による文字の候補
  5. クォートとエスケープ
  6. ワイルドカード利用時の注意
  7. grepと基本正規表現
  8. 位置を表す^$
  9. 正規表現の.[]*
  10. 実践的な検索と確認方法
  11. 30秒チェック
  12. 要約

ワイルドカードと正規表現の違い

ワイルドカードと正規表現は、どちらもパターンを使います。しかし、誰がパターンを解釈するのか、記号が何を意味するのかが異なります。

種類 主に解釈するもの 主な対象
シェルのワイルドカード bashなどのシェル ファイル名やパス名 ls *.txt
正規表現 grepsedawkなど ファイル内部の文字列 grep '^root:' /etc/passwd

シェルのワイルドカードは、グロブやパス名展開とも呼ばれます。シェルがパターンに一致するファイル名を探し、コマンドを実行する前に、そのパターンを実際のファイル名へ置き換えます。

printf '%s\n' *.txt

カレントディレクトリにa.txtb.txtがある場合、シェルは概ね次のような引数へ展開してからprintfを実行します。

printf '%s\n' a.txt b.txt

一方、次の'^root:'grepが解釈する正規表現です。

grep '^root:' /etc/passwd

シェルには正規表現を文字列のまま渡し、grepが各行の内容と照合します。

*によるファイル名展開

シェルのワイルドカード*は、0文字以上の任意の文字列に一致します。

ls *.txt
cp report* backup/
rm -- *.tmp

*.txtは、名前が.txtで終わるファイルに一致します。

パターン 一致する例 一致しない例
*.txt a.txtreport.txt report.csv
log* loglog1logs app.log
*backup* backupold-backup.tar archive.tar

*は0文字にも一致するため、log*logそのものにも一致します。

ディレクトリを含むパターン

ls /var/log/*.log
cp images/*.png backup/
ls project/*/README

通常のパス名展開では、*はスラッシュを越えて複数階層へ進みません。project/*/READMEでは、projectの直下にある一階層分のディレクトリ名へ一致します。

隠しファイル

bashの通常設定では、パターンの先頭にある*は、名前がドットで始まるファイルへ一致しません。

printf '%s\n' *
printf '%s\n' .*

隠しファイルを対象にする場合は、先頭のドットをパターンへ明示します。bashではdotglobを有効にし、通常のパターンへ隠しファイルを含める方法もあります。

shopt -s dotglob
printf '%s\n' *
shopt -u dotglob

dotglobはbash固有のシェルオプションです。スクリプトで変更する場合は、後続処理への影響も考えます。

?による1文字の指定

シェルのワイルドカード?は、任意の1文字に一致します。0文字や2文字には一致しません。

ls file?.txt
ls image-??.png
cp report-202?.pdf archive/
パターン 一致 不一致
file?.txt file1.txtfileA.txt file.txtfile10.txt
??.log 01.logab.log 1.log001.log

例えば、file?.txtは、file.txtの間に、ちょうど1文字がある名前へ一致します。

*との違い

file*.txt
file?.txt
  • file*.txt:間に0文字以上
  • file?.txt:間に必ず1文字

ファイル名の桁数が決まっている場合や、連番ファイルを絞り込む場合に便利です。

[]による文字の候補

角括弧[]は、括弧内に書いた候補のうち、いずれか1文字に一致します。

ls file[123].txt
ls image[ab].png
ls log[0-9].txt
パターン 意味
[abc] abcのいずれか1文字
[0-9] 範囲として扱われる1文字
[!abc] abc以外の1文字
[^abc] bashのパターンでは、abc以外の1文字として利用できる

file[123].txtは、file1.txtfile2.txtfile3.txtへ一致します。file12.txtには一致しません。

文字クラス

ls file[[:digit:]].txt
ls [[:upper:]]*.txt
ls *[[:space:]]*

角括弧の中では、POSIX文字クラスを利用できます。

文字クラス 主な意味
[[:digit:]] 数字
[[:alpha:]] 英字などの文字
[[:alnum:]] 英数字など
[[:lower:]] 小文字
[[:upper:]] 大文字
[[:space:]] 空白文字

範囲や文字クラスの一致結果はロケールの影響を受ける場合があります。正確なバイト順やASCII相当の動作を求める調査では、LC_ALL=Cを一時指定することがあります。

LC_ALL=C printf '%s\n' [A-Z]*

クォートとエスケープ

ワイルドカードをシェルに展開させず、記号そのものとしてコマンドへ渡したい場合は、クォートまたはバックスラッシュを使います。

printf '%s\n' "*.txt"
printf '%s\n' '*.txt'
printf '%s\n' \*.txt

これらは、*.txtという文字列をそのまま表示します。

クォートしない場合

printf '<%s>\n' *.txt

シェルが*.txtを一致するファイル名へ展開し、それぞれをprintfの引数として渡します。

正規表現をクォートする理由

grep '^root:' /etc/passwd
grep '[0-9]' data.txt
grep '.*\.log$' list.txt

grepへ渡す正規表現は、シングルクォートで囲むことが一般的です。シェルによるワイルドカード展開、変数展開、バックスラッシュの解釈などを防ぎ、パターンをそのままgrepへ渡せます。

ダブルクォートとの違い

pattern='^error'
grep "$pattern" app.log

ダブルクォート内では変数展開が行われます。変数へ保存した正規表現を渡す場合は、"$pattern"のようにダブルクォートで囲みます。

変数展開が不要な固定パターンでは、シングルクォートが分かりやすくなります。

文字どおりの検索

grep -F 'a.b*c[1]' file.txt

grep -Fは、パターンを正規表現ではなく固定文字列として扱います。正規表現の記号を多数含む文字列を、そのまま探したい場合に便利です。

ワイルドカード利用時の注意

展開結果を先に確認する

printf '%s\n' *.tmp
rm -- *.tmp

削除や移動の前に、printfなどで一致するファイル名を確認すると安全です。

オプションと誤解されるファイル名

展開されたファイル名がハイフンで始まると、コマンドのオプションとして解釈される場合があります。

rm -- *.tmp
cp -- *.txt backup/

--は、多くのコマンドでオプションの終わりを示します。以降の値をファイル名として扱わせます。

一致するファイルがない場合

bashの通常設定では、ワイルドカードに一致するファイルがない場合、パターン文字列が展開されずに残ります。

printf '<%s>\n' no-match-*.txt

一致がなければ、no-match-*.txtという文字列がそのまま渡されるのが標準的なbashの動作です。

bashでは、nullglobを有効にすると一致しないパターンを削除し、failglobを有効にするとエラーにできます。

shopt -s nullglob
files=(*.txt)
shopt -u nullglob

shopt -s failglob
printf '%s\n' no-match-*.txt
shopt -u failglob

これらはbash固有の設定であり、スクリプト全体へ影響します。必要な範囲を意識して使います。

隠しファイルと一括操作

*は通常、ドットで始まる名前へ一致しません。そのため、ディレクトリ内のすべてをコピーしたつもりでも、隠しファイルが含まれていない場合があります。

cp -a source/. destination/

ディレクトリの内容を隠しファイルも含めて複製する目的では、単純にsource/*とするより、コマンドの仕様に合う方法を使います。

パターンと実在ファイルを区別する

touch 'literal*.txt'
ls -l 'literal*.txt'

ファイル名自体に*などが含まれる場合は、クォートまたはエスケープして扱います。

grepと基本正規表現

grepは、入力からパターンに一致する行を検索します。オプションを付けない通常のgrepは、基本正規表現、BREを使います。

grep 'pattern' file.txt
grep -G 'pattern' file.txt

-Gは基本正規表現を明示します。通常は省略できます。

記号 基本正規表現での主な意味
. 任意の1文字
^ 行頭
$ 行末
[abc] abcのいずれか1文字
[^abc] abc以外の1文字
* 直前の要素を0回以上繰り返す
\{m,n\} 直前の要素を指定回数繰り返す
\(...\) 基本正規表現でのグループ化

拡張正規表現との違い

grep -E 'error|warning' app.log
grep -E 'colou?r' words.txt

grep -Eは拡張正規表現、EREを使います。拡張正規表現では、?+|()などをバックスラッシュなしで使います。

基本正規表現では、GNU grepで同様の機能を使う場合、\?\+\|\(...\)のように記述します。

位置を表す^$

^は行頭、$は行末を表すアンカーです。文字そのものではなく、行の位置に一致します。

行頭

grep '^root:' /etc/passwd
grep '^ERROR' app.log

^root:は、行の先頭がroot:で始まる行へ一致します。

行末

grep '/bin/bash$' /etc/passwd
grep '\.conf$' file-list.txt

/bin/bash$は、行末が/bin/bashで終わる行へ一致します。

行全体

grep '^yes$' answers.txt
grep '^127\.0\.0\.1$' addresses.txt

^yes$は、行全体がちょうどyesである行だけに一致します。

空行

grep '^$' file.txt
grep -n '^$' file.txt

^$は、行頭の直後に行末があるため、空行へ一致します。

空白だけの行

grep '^[[:space:]]*$' file.txt

[[:space:]]*は空白文字が0回以上続くことを表します。空行と、空白だけの行の両方に一致します。

コメント行

grep '^[[:space:]]*#' config.conf

行頭から空白が0文字以上続き、その後に#がある行を検索します。先頭に空白があるコメント行も対象になります。

正規表現の.[]*

.は任意の1文字

grep 'c.t' words.txt

c.tは、ctの間に任意の1文字がある部分へ一致します。例えば、catcotcutなどです。

ドットそのものを検索する場合は、バックスラッシュで特殊な意味を打ち消します。

grep '\.txt$' file-list.txt
grep '192\.168\.' addresses.txt

[]は候補のうち1文字

grep 'gr[ae]y' words.txt
grep '[0-9]' data.txt
grep '[^0-9]' data.txt
  • gr[ae]ygrayまたはgreyを含む文字列
  • [0-9]:範囲に含まれる1文字
  • [^0-9]:数字以外の1文字

正規表現の否定は、角括弧の直後に^を書きます。シェルのワイルドカードでは[!0-9]がよく使われるため、混同しないようにします。

文字クラス

grep '[[:digit:]]' data.txt
grep '^[[:alpha:]][[:alnum:]_]*$' names.txt
grep '[[:space:]]' file.txt

文字クラスは、ロケールに応じた文字の分類を表します。単純な英数字だけでなく、実行環境の文字集合を意識した検索に利用できます。

*は直前の要素を0回以上

grep 'ab*c' words.txt

ab*cでは、bが0回以上続きます。そのため、acabcabbcなどに一致します。

正規表現の*は、それ単独で任意の文字列を表すわけではありません。任意の文字列を表す組み合わせとしては、.*がよく使われます。

grep '^ERROR.*failed$' app.log

.が任意の1文字、*が直前のドットを0回以上繰り返すため、合わせて任意の文字列を表します。

繰り返し回数

grep '^[0-9]\{4\}$' years.txt
grep 'a\{2,4\}' words.txt

基本正規表現では、回数指定の波括弧をバックスラッシュでエスケープします。

  • \{4\}:ちょうど4回
  • \{2,4\}:2回以上4回以下
  • \{2,\}:2回以上

グループ化と後方参照

grep '^\(ab\)*$' words.txt
grep '^\([[:alpha:]]\+\) \1$' names.txt

基本正規表現では、\(...\)でグループ化します。\1は最初のグループと同じ文字列へ一致する後方参照です。GNU grepでは利用できますが、複雑な表現は読み間違いや処理負荷にも注意します。

実践的な検索と確認方法

1. ファイル名の展開結果を確認する

printf '<%s>\n' *.log
compgen -G '*.log'

削除や移動を行う前に、どのファイル名へ展開されるかを確認します。compgen -Gはbashでパターンに一致する名前を確認する方法の一つです。

2. ファイル内部の行頭を検索する

grep -n '^PermitRootLogin' /etc/ssh/sshd_config

-nを付けると行番号も表示されます。

3. コメントと空行を除く

grep -Ev '^[[:space:]]*(#|$)' config.conf

この例は拡張正規表現を使います。行頭から空白が続き、コメント記号または行末が続く行を除外します。

基本正規表現だけで段階的に処理する場合は、次のように分けられます。

grep -v '^[[:space:]]*#' config.conf \
  | grep -v '^[[:space:]]*$'

4. 完全一致を確認する

grep -x 'enabled' settings.txt
grep '^enabled$' settings.txt

grep -xは行全体がパターンへ一致する行を選びます。単純な固定文字列なら、grep -Fx 'enabled'とすると正規表現の解釈を避けられます。

5. パターンがハイフンで始まる場合

grep -- '-error' app.log
grep -e '-error' app.log

-errorをそのまま書くと、オプションと解釈される可能性があります。--でオプションを終了するか、-eでパターンを指定します。

6. 正規表現の記号を文字どおり探す

grep -F 'a.b*c[1]' file.txt
grep 'a\.b\*c\[1\]' file.txt

固定文字列として探せる場合は、grep -Fの方が意図を表しやすくなります。

7. ロケールを固定して確認する

LC_ALL=C grep '^[A-Z]' file.txt
LC_ALL=C sort file.txt

範囲表現や文字の分類、並べ替え結果が環境によって異なる場合は、一時的にLC_ALL=Cを指定して比較します。

ワイルドカードと正規表現の比較

目的 ワイルドカード 基本正規表現
任意の文字列 * .*
任意の1文字 ? .
候補の1文字 [abc] [abc]
候補以外の1文字 [!abc] [^abc]
行頭・行末 通常は扱わない ^$
主な利用対象 ファイル名 行内の文字列

症状別の確認

症状 主な確認点
*.txtがそのまま表示される 一致するファイルがあるか、クォートしていないか
隠しファイルが対象にならない 先頭ドットの明示、dotglob、コマンドのコピー方法
grepへ複数ファイル名が渡る 正規表現をクォートせず、シェルが展開していないか
ドットが任意の文字へ一致する 文字どおりのドットなら\.またはgrep -F
*の検索結果が想定と違う ワイルドカードか正規表現か、直前の要素は何か
範囲の一致が環境で変わる ロケール、文字クラス、LC_ALL=C

30秒チェック

  1. シェルのワイルドカードは、コマンドの実行前に誰が展開するでしょうか。
  2. ワイルドカードの*?は、それぞれ何文字に一致するでしょうか。
  3. file[123].txtは、どのようなファイル名に一致するでしょうか。
  4. ワイルドカードを展開させず、*.txtという文字列のまま渡すにはどうするでしょうか。
  5. 通常のgrepが使う正規表現は、基本正規表現と拡張正規表現のどちらでしょうか。
  6. 基本正規表現の.*は、それぞれ何を表すでしょうか。
  7. 空行へ一致する正規表現は何でしょうか。
  8. 正規表現の記号を解釈せず、固定文字列として検索するgrepのオプションは何でしょうか。
答えを表示
  1. bashなどのシェル
  2. *は0文字以上、?はちょうど1文字
  3. file1.txtfile2.txtfile3.txt
  4. シングルクォート、ダブルクォート、またはバックスラッシュで保護する
  5. 基本正規表現
  6. .は任意の1文字、*は直前の要素を0回以上繰り返す
  7. ^$
  8. -F

要約

  • ワイルドカードは主にシェルがファイル名へ展開し、正規表現はgrepなどが文字列の照合に使います。
  • シェルはコマンド実行前にワイルドカードを実在するファイル名へ置き換えます。
  • ワイルドカードの*は0文字以上、?は任意の1文字に一致します。
  • [abc]は候補のいずれか1文字、[!abc]は候補以外の1文字へ一致します。
  • *は通常スラッシュを越えず、先頭がドットの隠しファイルにも一致しません。
  • ワイルドカードを文字どおり渡す場合は、クォートまたはバックスラッシュで保護します。
  • 削除や移動の前には、printfなどで展開結果を確認すると安全です。
  • bashの通常設定では、一致しないワイルドカードは展開されず、そのまま残ります。
  • 通常のgrepは基本正規表現、grep -Eは拡張正規表現、grep -Fは固定文字列検索です。
  • 正規表現の^は行頭、$は行末、.は任意の1文字を表します。
  • 正規表現の*は、直前の要素を0回以上繰り返します。
  • 正規表現で任意の文字列を表す代表的な組み合わせは.*です。
  • 文字どおりのドットを検索する場合は\.、固定文字列全体ならgrep -Fを使えます。
  • 空行は^$、空白だけの行も含める場合は^[[:space:]]*$で検索できます。
  • 範囲や文字クラスの結果はロケールの影響を受ける場合があり、確認時にLC_ALL=Cを使うことがあります。

参考資料