はじめに
正規表現をつかうことで文字列を様々なパターンで検索したり置換することができます。
同じパターンが連続するようなケースでは、繰り返しパターンを使用するとより明瞭に書くことができます。
本記事では正規表現で使用できる繰り返しパターンの指定方法についてまとめます。
正規表現の文字クラスやフラグについては以下で扱っています。
繰り返しパターン
/\d\d\d-\d\d\d\d/のように同じパターン\dが何度も出てくる際には、繰り返しパターンを使用して記述を簡略化できます。
/\d\d\d-\d\d\d\d/は、繰り返しパターンを使うと/\d{3}-\d{4}/のようにできます。
繰り返しパターンには以下のようなものがあります。
{n, m}
{n, m}はn回以上、m回以下の繰り返しを表します。
例えば、/a{3,6}/について例をみてみます。
const regex = /a{3,6}/
"aaaa".match(regex) //["aaaa"]
"aaaaaaa".match(regex) //["aaaaaa"]
regex.test("aaa") //true
regex.test("aaaaaaa") //true
/a{3,6}/は、aが3回以上6回以下のなかで最長回数となる箇所にマッチするため、"aaaa"に対しては"aaaa"がそのままマッチし、"aaaaaaa"とaが7回続くケースでは6回分の繰り返しである"aaaaaa"にマッチすることになります。
7回以上続く場合にマッチしないわけではない点に注意が必要ですね。
{n,}
{n,}はn回以上の繰り返しを表します。
{n}
{n}はn回だけの繰り返しを表します。
{n,n}と同じものですね。
*
*は0回以上の繰り返しを表します。
{0,}と同じもので、より簡潔に記述できます。
.
.は1回以上の繰り返しを表します。
{1,}と同じものです。
?
?は0回以上1回以下の繰り返しを表します。
{0,1}と同じもので
貪欲な繰り返しパターン
正規表現では、マッチ箇所をみつけたあとにもパターンの規則を満たす限り、マッチ箇所の先の探索を続けます(greedyマッチング)。
パターンの規則に合致した箇所が複数ある場合には最も長い箇所にマッチします(最長一致)。
/a{3,6}/という正規表現では、"aaaab"を先頭の文字から確認していきます。
最初の3つの"a"だけでも/a{3,6}/のパターン規則を満たしますが、それに続く4つ目の"a"を含めた"aaaa"もパターン規則を満たします。
また、"aaaab"自体はパターン規則を満たさないため、パターンに合致した中で最長となる"aaaa"の部分がマッチすることになります。
非貪欲な繰り返しパターン
繰り返しパターンのあとに?をつけると最小一致によるマッチがなされます。
const regex = /a{3,6}?/
"aaaa".match(regex) //["aaa"]
"aaaaaaa".match(regex) //["aaa"]
regex.test("aaa") //true
regex.test("aaaaaaa") //true
?については繰り返しパターンで使用していた記法*, ., ?につけることも可能で、それぞれ*?, .?, ??で最小一致によるマッチングが行えます。