「欲張らない繰り返し」ぐらいまで理解しよう。

正規表現はクラスの使い方より、
パターンを作る方が本題であるし難しい。

ここでは正規表現について、「繰り返し」が理解できるぐらいにまとめる。
「欲張らない繰り返し」ぐらいまで理解できていれば、大体困らない。

単語の一致

pen

単純な単語に思えるが、正規表現上の解釈としては次のように考える。
「まずpがあり、その直後にeがあり、その直後にnがある場合にマッチする」

単語だけの正規表現は実際にはあまり使わない。
単語のマッチであればString.contains()などで十分。
ここでは、正規表現の考え方の基本をおさえておく。

ドット

p.n

「.」は、任意の1文字とマッチさせる。

1文字というところが重要。

複数の任意文字としたい場合は、
繰り返しと組み合わせなくてはならない。

「.」自体はあくまでも1文字。

この1文字は単語、空白、記号など何でもいい。

文字クラス

p[ea]n

「[]」は、かっこ内で指定したテキスト1文字にマッチさせる。

この文字クラスも、
1文字というところが重要。
文字クラス内がどんなに長くなろうと、
表しているのは1文字。

また、文字クラス内は「orつなぎ」で
考えなくてはいけないことも重要。

通常の正規表現は「andつなぎ」である。

単語の一致の例パターンでは、
「まずpがある」and「その直後にeがある」and「その直後にnがある」場合にマッチする
という解釈と考えられる。

一方、ここ(文字クラス)の例パターンで考えると、
「まずpがある」 and (「その直後にeがある」 or 「その直後にaがある」)and 「その直後にnがある」場合にマッチする
という解釈をする。

範囲を示す「-」

[0-9]

「-」を使うことで範囲を示せる。
[0123456789]と書かなくてよい。

文字クラス内と文字クラス外では意味が変わるメタ文字

これを知っていないと、はまる可能性がある。

例えば、「.」は文字クラス外では先ほど説明したように任意の1文字である。
ただこれが文字クラス内に入ると、ただの記号としての「.」ということになる。
(任意の1文字ではなくなる。)

文字 通常(文字クラス外) 文字クラス内 備考
. 任意の1文字 「.」記号
| 選択 「|」記号
( 範囲の始まり 「(」記号
) 範囲の終わり 「)」記号
- 「-」記号 範囲を示す

選択

pan|pen

「|」は、またはの意味になる。

選択の対象になった部分は、
通常の正規表現として扱われる。

()で範囲を限定

p(a|e)n

「()」で選択対象を限定できるので、
普通は利用する。

「()」がない場合は、範囲が全般に及んでしまう。

繰り返し

pe*n

「*」は、繰り返しを意味する。
繰り返すのは直前の要素である。

繰り返しの回数によって、
記号が変わる。

記号 繰り返し回数
? 0回以上-1回
* 0回以上-無限
+ 1回以上-無限
X{n} n回
X{n,} n回以上
X{n,m} n回以上-m 回以下

欲張らない繰り返し

例えば、次のテキストから<li>で囲まれた部分の抽出を考える。

<ul><li>baseball</li><li>soccer</li></ul>

先ほどの繰り返しを利用すると、
次のように考えられる。

<li>.*</li>

この正規表現で抽出すると、
次の結果になる。

<li>baseball</li><li>soccer</li>

これでは、最初の<li>で囲まれた部分だけを抽出したいときに困る。
この場合は、繰り返しに「?」を加えることで解決する。

<li>.*?</li>

この正規表現で抽出すると、
次の結果になる。

<li>baseball</li>

この2つの例からわかるように、
通常の繰り返しではできる限りたくさんマッチさせようとする。
(いわゆる欲張りな繰り返し)

よって、部分抽出など繰り返しの範囲を狭くしたい場合は
「?」(最短一致数量子)を指定する。

PR