正規表現では、複数回連続させた数字やアルファベットをマッチさせたいことが度々あります。

例えば、"12345"は正規表現で\d\d\d\d\dと記述することができますが、量指定子を使ってマッチさせたい数字の数を指定することができます。

今回は、文字を指定した回数繰り返すことができる量指定子について解説していきます。

0から1回の繰り返し*+?

0から1回の文字の繰り返しには、簡略表記として*+?が使われます。

0回以上の連続*

アスタリスク*は、直前の文字が0回以上連続する文字列にマッチします。
0回以上とは、任意の数文字を繰り返しさせることもできますが、一度も出現しない場合も含みます。

例えば\d1*は、任意の数字と0回以上の"1"という意味になります。

let reg = /\d1*/g;

console.log('51 5111 5'.match(reg)); // ["51", "5111", "5"]

直前の文字が0回以上となるため、入力文字が"5"だけの場合も対象です。

1回以上の連続+

プラス+は、直前の文字が1回以上連続する文字列にマッチします。

例えば\d1+は、任意の数字と1回以上の"1"です。
先程のアスタリスク*の例と比べてみましょう。

let reg1 = /\d1*/g;
let reg2 = /\d1+/g;

console.log('51 5111 5'.match(reg1)); // ["51", "5111", "5"]
console.log('51 5111 5'.match(reg2)); // ["51", "5111"]

アスタリスク*とは少し異なり、プラス+の場合は、入力文字が"5"だけでは条件に満たしません。
このように、文字の出現を1回は保証したい時に使えます。

0回または1回の出現?

疑問符?は、直前の文字が0回または1回出現する場合にマッチします。

以下のように、イギリス英語とアメリカ英語で単語の綴りが若干異なることがあります。

  • イギリス英語:neighbour
  • アメリカ英語:neighbor

そこで例えばneighbou?rは、"neighbo"に続いて0または1回の"u"、そして"r"にマッチします。

let reg = /neighbou?r/g;
let str = 'Both of neighbour and neighbor are correct.'

console.log(str.match(reg)); // ["neighbour", "neighbor"]

これでどちらの綴りにも適用できます。

回数指定{}

波括弧{}は、文字がどれだけ必要か正確に指定することができます。

指定の数繰り返し{n}

{n}は、直前の文字をn回繰り返す文字列にマッチします。

"12345"は正規表現で\d\d\d\d\dと表すこともできますが、波括弧{n}を使うと\d{5}と書くことができます。

例えば、生年月日の入力を行う際、「4桁の年/2桁の月/2桁の日」のフォーマットでの入力を求められることが良くあります。
その場合、以下のようにして年月日の桁指定を行うことができます。

let reg = /\d{4}\/\d{2}\/\d{2}/;
let str = 'I was born in 1998/01/31';

console.log(str.match(reg)); // ["1998/01/31"]

年月日を区切るスラッシュ/は、エスケープ\して文字として認識させています。

指定の範囲内で繰り返し{from,to}

{from,to}は、直前の文字をfromからtoまでの範囲内で繰り返す文字列にマッチします。

以下は、2桁から4桁の数字を探します。

let reg = /\d{2,4}/g;

console.log('1 10 100 1000'.match(reg)); // ["10", "100", "1000"]

toの指定は省略して上限を設定しないようにすることもできます。
例えば、3桁以上の数字を探す場合このように書けます。

let reg = /\d{3,}/g;

console.log('1 10 100 1000'.match(reg)); // ["100", "1000"]

ここまでで正規表現の量指定子の使い方が分かりました。

最後に、入力フォームなどで良く見られる郵便番号と電話番号のテストを行ってみましょう。
どちらも数字の規則的な繰り返しパターンが見られるため、量指定子が使えます。

郵便番号(ハイフン任意)

郵便番号を以下の条件の元でパターンチェックを行います。

  • ^[0-9]{3}:3桁の数字で始まる
  • \-?:真ん中のハイフンは任意
  • [0-9]{4}$:4桁の数字で終わる
let reg = /^[0-9]{3}\-?[0-9]{4}$/;

let str1 = '123-4567';
let str2 = '1234567';
let str3 = '12-3456';

console.log(reg.test(str1)); // true
console.log(reg.test(str2)); // true
console.log(reg.test(str3)); // false

携帯番号(ハイフンあり)

次の携帯番号のパターンチェックは以下の条件の元行われています。

  • ^0:0で始まる
  • [5789]0:5,7,8,9いずれかの数字と0
  • \-:ハイフン
  • [0-9]{4}:数字4桁
  • \-:ハイフン
  • [0-9]{4}$:数字4桁で終わる
let reg = /^0[5789]0\-[0-9]{4}\-[0-9]{4}$/;

let str1 = '080-1234-5678';
let str2 = '050-9876-5432';
let str3 = '09011111111';
let str4 = '030-5555-3333';

console.log(reg.test(str1)); // true
console.log(reg.test(str2)); // true
console.log(reg.test(str3)); // false
console.log(reg.test(str4)); // false

正規表現で表せるパターンはこの限りではありませんが、まずは一つの例として読み解くのも理解に繋がります。

まとめ

今回は、量指定子について解説しました。

// ポイント
* アスタリスク*:直前の文字が0回以上連続する文字列にマッチする
* プラス+:直前の文字が1回以上連続する文字列にマッチする
* 疑問符?:直前の文字が0回または1回出現する文字列にマッチする
* {n}:直前の文字をn回繰り返す文字列にマッチする
* {from,to}:直前の文字をfromからtoまでの範囲内で繰り返す文字列にマッチする

合わせて読みたい正規表現シリーズ

第1回:正規表現の概要
第2回:文字クラス
第3回:文字集合と範囲
第4回:文字列の先頭と末尾
第5回:量指定子(当記事)