コピペで済ませてきた正規表現をちゃんと勉強してみる

前いた会社で正規表現をほとんど使う機会がなく、転職した現在の会社で正規表現の知識が必要になったのでちゃんと勉強することにしました。
ひろゆきにならってとほほの正規表現入門を使用して勉強しました。

https://youtu.be/VpmF9Hf_rMM

参考資料:

https://www.tohoho-web.com/ex/regexp.html

https://murashun.jp/article/programming/regular-expression.html

https://qiita.com/str32/items/a692073af32757618042#url

### 使用したツール

https://weblabo.oscasierra.net/tools/regex/

こちらを使っていきます。

### 普通に同じ文字でマッチ

![スクリーンショット 2021-10-15 7.51.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/b9f84c57-b57c-4df5-f535-005ced7a2a3a.png)

### メタ文字

メタ文字とは

> メタ文字とは、その文字本来の意味とは異なり、プログラムで特別な意味を持たせた文字のことである。 例えば、正規表現では「+」は「足す」ではなく1回以上の連続文字を意味するメタ文字である。 正規表現による検索では、A+Bで検索すれば、AB、AAB、AAABなどのいずれとも一致する。

###　数字でマッチ

`\d`を使うと数字をマッチさせることができます

![スクリーンショット 2021-10-15 13.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/0e854283-df97-1cf6-51e1-66d087a1932c.png)

### 英数字でマッチ

`\w`を使うと英数字をマッチさせることができます

![スクリーンショット 2021-10-15 13.15.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/4a8b249f-6a31-f8da-7371-3bd0464b0662.png)


### `.`を使用

`. => 任意の一文字にマッチ`

![スクリーンショット 2021-10-15 7.52.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/e79da513-6183-594c-d334-9be779e35f9f.png)

### [ ]を使用

`[ ] => [ ]の中に入れた特定の文字にマッチ`

![スクリーンショット 2021-10-15 7.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/80eb962e-fc3b-404c-d167-181eb2be0d1c.png)

また[ ]は`-`を入れることで範囲マッチもできるようになる

例えば
は~ふまでの文字を `-`を入れて使用すると`ほ`はその範囲内ではないのでマッチしません。

![スクリーンショット 2021-10-15 8.05.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/e9a1b6a0-7a34-d691-6cc2-c26fbcb776b0.png)

数字もいけます

![スクリーンショット 2021-10-15 8.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/86d1dc2c-83dc-27ac-7bff-9e9f8e0689c0.png)

ひらがな全てを表す場合、

[ぁ-ん]

カタカナ全てを表す場合

[ァ-ヴ]

で表す。

小文字から始まるのが変に思えるのですがこれは文字コード表の順番で決まります。

http://orange-factory.com/sample/utf8/code3/e3.html#Hiragana

文字コード表を見ると普段見慣れない「ゐ、ゑ」は「ん」よりも前にあり、範囲内なのでマッチします

![スクリーンショット 2021-10-15 8.13.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/83444290-3488-3494-4eca-e8c7fb8ce47a.png)

### グループ化

`()`を使うことで()内のどれかにマッチします。文字の区切りには `|`を使用します。

![スクリーンショット 2021-10-15 8.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/2a51c6ef-8dcc-29e9-6fa8-e34fd84a1018.png)

### 先頭マッチ

`^`を使うことで先頭の文字のみマッチします

![スクリーンショット 2021-10-15 8.32.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/7bfb8b07-cf7b-7a79-c601-412a6bd8a667.png)

`Java`という文字は文の中で2つあるのですが、`^`を使用したことにより、文の先頭のJava部分だけマッチしました。

### 末尾マッチ

`$`を使うことで末尾の文字のみマッチします

![スクリーンショット 2021-10-15 8.34.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/dfedf06b-c3b6-dd42-cd89-662f7dd700b3.png)

これは先程の先頭マッチの逆です。
また$を書く位置も関係します。

### 繰り返し文字マッチ

`*`を使うと0回以上繰り返す文字にマッチ

「」がついている文字を探したりするのに使えます。

![スクリーンショット 2021-10-15 8.42.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/3edcadda-2ff5-a547-3b73-cf34a3913ca2.png)

後はこんな感じの使い方もできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/15647ee4-5b8d-d9fe-4a96-5f8e808a5dfb.png)

`+`を使うと1回以上繰り返す文字にマッチ

`*`を使って「」をマッチさせていましたが、実は「」の中が空でもマッチしてしまいます。

![スクリーンショット 2021-10-15 9.00.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/2beda4be-bec5-896f-81e2-844429fb8251.png)

そこでこれを防ぐためには1回以上繰り返す文字にマッチする`+`を使います。


![スクリーンショット 2021-10-15 8.58.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/b04ae250-7110-24fa-d133-4f42d6070b74.png)

こうすることで「」の中に何も文字が入っていない(1つ以上の文字が入っていない)ため、マッチさせることなく検出できるようになりました。

`?`を使うとあってもなくてもマッチ

`a`という文字があってもなくてもマッチされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/f7d42957-956f-abd8-3ebd-fbb087b81f72.png)

`{n}`を使うと繰り返しの数を指定できます。

「CoffeeScript」は続けて使われる箇所(`ff`と`ee`)があるので繰り返しマッチを使えます。

![スクリーンショット 2021-10-15 9.17.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/f1beb201-a9dc-344f-4eef-9e75554079bb.png)

`{n,m}`使うと繰り返しの範囲を指定できます。

![スクリーンショット 2021-10-15 13.11.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660329/3f3ed76d-c907-78f8-e7fd-e6bc0fe78687.png)

### 今までコピペで済ませてきた正規表現を勉強した知識で読み解いてみる

出典: [基本的な正規表現一覧](https://murashun.jp/article/programming/regular-expression.html)

### Email アドレス (RFC準拠ではない)

```
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
```

1. 1文字以上の英数字（\w+）で始まる　`\w+`
2. 0文字以上の`-`か`+`か`.`か`'`のどれか(`[-+.']`)と英数字を含めた文字 `([-+.]\w+)*)`
3. @の後は1文字以上の英数字と0文字以上の、`-`か`.`のどれか(`[-.]`)と英数字を含めた文字 `(@\w+[-.]\w+)*`
4. コロンと一文字以上の英数字と0文字以上の　`-`か`.`のどれか(`[-.]`)と英数字を含めた文字 \.\w+([-.]\w+)*


### URL

```
^https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
```

1. `s?`の部分でsがあってもなくてもおkとしています。つまり`http`or`https`のどちらかということです
2. 一文字以上の'-'を含めた英数字とコロン`([\w-]+\.)+`
3. 一文字以上の'-'を含めた英数字 `[\w-]+`
4. 0文字以上の`-`と`.`と`/`と`?`と`%`と`&`と`=`を含めた英数字 　`(/[\w-./?%&=]*)?`

### ドメイン名
```
^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z-]{2,}$
```

ドメインの基礎知識が必要になります

> ピリオド(.)で区切られた部分は「ラベル」と呼ばれます。 一つのラベルの長さは63文字以下、ドメイン名全体の長さは、 ピリオドを含めて253文字以下でなければなりません。※1 ラベルには、英字(A～Z)、数字(0～9)、 ハイフン( - )が使用できます(ラベルの先頭と末尾の文字をハイフンとするのは不可)。 ラベル中では大文字・小文字の区別はなく、 同じ文字とみなされます。

https://www.nic.ad.jp/ja/dom/system.html#:~:text=%E4%B8%80%E3%81%A4%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E3%81%AE%E9%95%B7,%E6%96%87%E5%AD%97%E3%81%A8%E3%81%BF%E3%81%AA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

長いので2つに分けます

① `[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]`
先頭と末尾をハイフンにするということができないので、`[a-zA-Z0-9]`で-を入力できる正規表現をラップしています。
もし先頭と末尾にハイフンが入れられたら前半部分は`[a-zA-Z0-9-]{1,63}`だけで表現できるということですね

② `\.[a-zA-Z-]{2,}`
`\.`はドットがメタ文字(バックスラッシュなしで使うといずれかの1文字の意味)なのでバックスラッシュでエスケープしてます
また最後の{2,}は2文字以上の意味で
まとめると\.[a-zA-Z-]{2,}小文字、大文字の2文字以上の英字

example.comの`.com`の部分です

### 固定電話番号

```
^0\d(-\d{4}|\d-\d{3}|\d\d-\d\d|\d{3}-\d)-\d{4}$
```
1. 0から始まり

### 携帯電話番号

```
^0[789]0-\d{4}-\d{4}$
```
1. 必ず0から始まります
2. 2つ目の数字は789のどれかです
3. 真ん中の数字と最後の数字は4桁の数字です  

### IP 電話番号

```
^050-\d{4}-\d{4}$
```

1. 必ず`050` から始まります
2. 真ん中の数字と最後の数字は4桁の数字です  

### フリーダイヤル

```
^(0120|0800)-\d{3}-\d{3}$
```

1. 最初の数字は必ず`0120`もしくは`0800`で始まります
2. 真ん中の数字と最後の数字は4桁の数字です

### 日付 (YYYY-MM-DD形式)

```
^\d{4}-\d\d-\d\d$
```

1. 西暦が4桁で月が2桁、日が2桁です
// 何で`^\d{4}-\d{2}-d{2}`じゃないのか分からないので詳しい人いたら教えて下さい

### 郵便番号
```
^\d{3}-\d{4}$
```

1. 必ず最初の数字が3桁で次の数字が4桁です

### 感想
高校生の頃ちゃんと英語勉強した後に試験受けた時の「読める....!」という感覚になりました
またEmail,URL,ドメインは初見でわからなかったのでカンニングしました。