【JavaScript】正規表現を好きになろう

正規表現の勉強をしたのでまとめました。

#正規表現とは

正規表現とは、文字列のパターンマッチングに特化した言語です。

#正規表現の用語

正規表現の用語を整理します。

**パターン**
探したい規則をパターン(pattern)と呼びます。
**シーケンス**
パターンを探す対象文字列を入力シーケンスと呼びます。
**マッチ**
入力シーケンスの中でパターンに一致する文字列が見つかることをマッチ（match）すると言います。

パターンとシーケンスを噛み砕いて説明すると、
「**l**で始まり**e**で終わる単語」がパターンで、"I love JavaScript"が入力シーケンスです。


#正規表現の文法

正規表現は言語の一種なので文法を持ちます。
しかし、JavaScriptから想像するような文法とは異なります。
あくまでパターンマッチングのための記法の一つと見なす方が理解しやすいと思います。


####正規表現のメタ文字

|メタ文字  |意味  |
|---|---|
|.  |任意の一文字  |
|\s  |空白文字  |
|\S  |非空白文字  |
|\w  |単語構成文字（英数字とアンダースコア文字）  |
|\W  |非単語構成文字  |
|\d  |数字  |
|\D  |数字以外の文字  |
|\b  |単語境界  |
|\B  |非単語境界  |
|^  |行頭  |
|$  |行末  |
|X?  |Xの0文字または1文字の繰り返し  |
|X??  |Xの0文字または1文字の繰り返し(非貪欲)  |
|X*  |Xの0文字以上の繰り返し  |
|X*?  |Xの0文字以上の繰り返し（非貪欲）  |
|X+  |Xの1文字以上の繰り返し  |
|X+?  |Xの0文字以上の繰り返し（非貪欲）  |
|X{n}  |Xのn回の繰り返し  |
|X{n}?  |Xのn回の繰り返し（非貪欲）  |
|X{n,}  |Xのn回以上の繰り返し  |
|X{n,}?  |Xのn回以上の繰り返し(非貪欲)  |
|X{n,m}  |Xのn回からm回の繰り返し  |
|X{n,m}?  |Xのn回からm回の繰り返し（非貪欲）  |
|X|Y  |XまたはY  |
|[XYZ]  |XまたはYまたはZの1文字  |
|[^XYZ]  |XでもYでもZでもない1文字  |
|(X)  |グループ化(参照可能)  |
|\数字  |マッチグループの参照  |
|(?:X)  |グループ化のみ（参照しない）  |
|X(?=Y)  |Xの後にYが続く場合にマッチ  |
|X(?!Y)  |Xの後にYが続かない場合にマッチ  |

メタ文字を使う記号をメタ記号扱いしたく無い場合はバックスラッシュ文字でエスケープします。
例えば、ドット文字（.）にマッチさせたいパターンには`\.`と書きます。
バックスラッシュ文字にマッチするパターンを書く時は`\\`と書きます。
その他にもJavaScript文字列と似たようなエスケープシーケンスが使えます。

####正規表現のエスケープシーケンス

|特殊文字（エスケープシーケンス） |意味  |
|---|---|
|\n  |改行(LF) |
|\t  |タブ  |
|\r  |改行(CR)  |
|\f  |フィード |
|\f  |垂直タブ |

####正規表現のフラグ

|フラグ |説明  |
|---|---|
|g  |グローバルマッチ |
|i  |英字の大文字小文字を区別しない  |
|m  |マルチライン。^と$がそれぞれの改行の先頭や末尾にもマッチするようになる  |

#正規表現

JavaScriptで正規表現を扱うには正規表現オブジェクトを使います。
正規表現オブジェクトは**RegExpクラスの**のインスタンスオブジェクトです。
また、リテラル表記でも生成可能です。

```js
var reg = new RegExp('^[0-9]$');  // 正規表現 ^[0-9]$ のパターンRegExpインスタンス生成
var reg = /^[0-9]$/;  // リテラル表記でも生成できます。
```


##matchメソッド



```js
var test = 'abcdefg' // 変数testに入力シーケンスを代入
var result = test.match(/[a-z]/gi); // 変数resultにマッチした結果を配列で返す
console.log(result);
 (7) ["a", "b", "c", "d", "e", "f", "g"]
```

matchメソッドは、パターンにマッチした部分文字列を要素に持つ配列を返します。
グローバルフラグの有無で返り値の意味が変わります。
グローバルフラグが存在してる場合は、入力シーケンスの中でマッチした全ての部分文字列を持つ配列を返します。

##execメソッド

```js

var test = "abcdefg"
var result = /(.+)de(fg)/.exec(test);
console.log(result);
(3) ["abcdefg", "abc", "fg", index: 0, input: "abcdefg", groups: undefined]
```

execメソッドは、パターンにマッチした部分文字列を要素に持つ配列を返します。
返した配列の[0]にはマッチした範囲の文字列全体が返ります。
[1]以降は、カッコ（ ）で囲まれた部分の文字列のマッチがセットされます。
マッチしない場合は、nullを返します。


##testメソッド

```js

var test = '0123456789' // 変数testに入力シーケンスを代入
var result = /[0-9]{6}/.test(test) // testメソッドの引数に変数testを渡す
console.log(result);
true  // 入力シーケンス'0123456789'に対してマッチ => 結果はtrue

```

入力シーケンスを検索し、結果はブーリアン形式で返す。

##searchメソッド

```js

var test = "abcdefg";
var result = test.search(/fg/);
console.log(result);
5
```
searchメソッドは、指定された正規表現で最初にマッチした文字位置を返す。
0からカウントして数字を返すが、マッチした文字列が存在しない場合は、戻り値として-1を返す。

##replaceメソッド

```js

var test = "abc def ghi jkl";
var result = test.replace(/\s/g, ','); // 変数testに格納された文字列の空白を「,」と置換
console.log(result);
abc,def,ghi,jkl

```

```js

var test = "Tanaka Taro";
var result = test.replace(/(\w+)\s(\w+)/, "$2, $1");  // $1にはTanaka $2にはTaro
console.log(result);
Taro,Tanaka

```
replaceメソッドは、正規表現でマッチした文字列を置換することができます。

##splitメソッド

```js

console.log('2021/5/30'.split(/[\/\.\-]/));  // 「/」,「-」,「.」を区切って年月日に分割するコード
["2021", "5", "30"]
console.log('2021-5-30'.split(/[\/\.\-]/));
["2021", "5", "30"]
console.log('2021.5.30'.split(/[\/\.\-]/));
["2021", "5", "30"]
```

splitメソッドは、正規表現で文字列を分割することができる。
splitメソッドの第二引数に分割回数の上限値を渡すこともできます。



以上です。
ちょっとずつ使いこなして正規表現マスターになります！