第10章 正規表現

基本的な構文と特殊文字

正規表現は様々な特殊文字を使ってパターンを表現します。

const regex = /abc/; // "abc"という文字列を検索する正規表現
const str = "abcdef";
console.log(str.match(regex)); // ["abc", index: 0, input: "abcdef", groups: undefined]


文字クラス

特定の種類の文字をマッチさせるためのパターン。

const digits = /\d/; // 任意の数字を検索する正規表現
const str2 = "apple123banana";
console.log(str2.match(digits)); // ["1", index: 5, input: "apple123banana", groups: undefined]


繰り返し

同じパターンの繰り返しを検索する。

const repeatedDigits = /\d+/; // 1回以上の数字の繰り返しを検索
const str3 = "apple123banana45";
console.log(str3.match(repeatedDigits)); // ["123", index: 5, input: "apple123banana45", groups: undefined]


選択、グループ化、参照

異なるパターンのいずれかをマッチさせる。

const colors = /red|blue|green/; // "red"、"blue"、または"green"を検索
const str4 = "apple red banana blue";
console.log(str4.match(colors)); // ["red", index: 6, input: "apple red banana blue", groups: undefined]


バウンダリマッチャー

文字列や単語の境界を指定してマッチさせる。

const wordBoundary = /\bapple\b/; // "apple"という単語全体を検索
const str5 = "apple pie pineapple";
console.log(str5.match(wordBoundary)); // ["apple", index: 0, input: "apple pie pineapple", groups: undefined]


フラグ

正規表現の振る舞いを変えるためのフラグ。

const caseInsensitive = /apple/i; // 大文字小文字を区別せず"apple"を検索
const str6 = "Apple pie";
console.log(str6.match(caseInsensitive)); // ["Apple", index: 0, input: "Apple pie", groups: undefined]


肯定的・否定的先読み

特定の文字が続くか、続かないかを基にマッチする。

const posLookahead = /q(?=u)/; // 'q'に直後に'u'が続く場所を検索
const str7 = "queen";
console.log(str7.match(posLookahead)); // ["q", index: 0, input: "queen", groups: undefined]

const negLookahead = /q(?!u)/; // 'q'に直後に'u'が続かない場所を検索
const str8 = "qatar";
console.log(str8.match(negLookahead)); // ["q", index: 0, input: "qatar", groups: undefined]


文字セットと否定文字セット

特定の文字セットの中から1文字をマッチさせる。否定文字セットは指定したセットの文字以外をマッチ。

const charset = /[aeiou]/; // 母音を検索
const str9 = "hello";
console.log(str9.match(charset)); // ["e", index: 1, input: "hello", groups: undefined]

const negCharset = /[^aeiou]/; // 母音以外を検索
console.log(str9.match(negCharset)); // ["h", index: 0, input: "hello", groups: undefined]


バックリファレンス

以前にマッチしたグループと同じ内容を再度マッチさせる。

const backRef = /(abc)\1/; // "abcabc"のような繰り返しを検索
const str10 = "abcabc";
console.log(str10.match(backRef)); // ["abcabc", "abc", index: 0, input: "abcabc", groups: undefined]


Unicode プロパティエスケープ

特定のUnicodeプロパティにマッチする文字を検索する。

const unicodeProp = /\p{Script=Hiragana}/u; // ひらがな文字を検索
const str11 = "こんにちは";
console.log(str11.match(unicodeProp)); // ["こ", index: 0, input: "こんにちは", groups: undefined]


マッチパターンの一覧(一部)

マッチパターン 内容
. 任意の文字(改行文字を除く)にマッチ
\d 数字にマッチ([0-9]と同等)
\D 数字以外にマッチ([^0-9]と同等)
\w 単語構成文字([a-zA-Z0-9_]と同等)にマッチ
\W 単語構成文字以外にマッチ
\s 空白文字(スペース、タブ、改行、フォームフィード)にマッチ
\S 空白文字以外にマッチ
\b 単語の境界にマッチ
\B 単語の境界以外にマッチ
^ 文字列の先頭、または多行モードでの行の先頭にマッチ
$ 文字列の末尾、または多行モードでの行の末尾にマッチ
n n番目のキャプチャグループにマッチ
[...] 指定された文字のいずれか1文字にマッチ
[^...] 指定された文字以外のいずれか1文字にマッチ
* 直前の要素が0回以上続く場所にマッチ
+ 直前の要素が1回以上続く場所にマッチ
? 直前の要素が0回または1回続く場所にマッチ
{n} 直前の要素がn回続く場所にマッチ
{n,} 直前の要素がn回以上続く場所にマッチ
{n,m} 直前の要素がn回以上、m回以下続く場所にマッチ
| OR(または)演算子
( ...) キャプチャグループ
(?: ...) キャプチャしないグループ
(?= ...) 肯定的先読み
(?! ...) 否定的先読み
\\ \自体にマッチ
\t タブにマッチ
\r キャリッジリターンにマッチ
\n 改行にマッチ
\f フォームフィードにマッチ
\v 垂直タブにマッチ
\xNN 16進数で指定された文字にマッチ (Nは0-9、a-fまたはA-F)
\uNNNN 16進数で指定されたUnicode文字にマッチ

正規表現は非常に複雑で、このような基本的な特性から高度な特性まで多岐にわたります。これらのカテゴリをしっかりと理解することで、より高度なパターンマッチングを行うことができるようになります。


練習問題1.

以下の形式の電話番号をマッチさせる正規表現を書いてください。

形式: 0XX-XXXX-XXXX

Xは0-9の数字

012-3456-7890  // マッチする
0123-456-7890 // マッチしない
123-4567-8901 // マッチしない
012-3456-789A // マッチしない


練習問題2.

以下の基本的な条件を満たすメールアドレスをマッチさせる正規表現を書いてください。

ローカル部とドメイン部が"@"で区切られている

ローカル部は英数字とドット(.)が利用可能

ドメイン部は英数字とハイフン(-)、ドット(.)が利用可能で、最後はドット(.)に続く2〜6文字の英字)

test.email@example.com      // マッチする
test.email@sub.example.com  // マッチする
test.email@example          // マッチしない
test.email@example.c        // マッチしない
test.email@example.toolong  // マッチしない


練習問題3.

以下の形式の日付をマッチさせる正規表現を書いてください。

形式: YYYY/MM/DD

Yは4桁の年 (例: 2023)

Mは1〜2桁の月 (例: 7 or 07)

Dは1〜2桁の日 (例: 5 or 05)

2023/7/5     // マッチする
2023/07/05   // マッチする
2023/7/35    // マッチしない (日にちが不正)
2023/13/05   // マッチしない (月が不正)
202/07/05    // マッチしない (年が3桁)