正規表現説明とよく使うパターンをまとめる

`正規表現の説明`と`よく使うパターン`を備忘録としてまとめます。
あわせて書き方による`実行時間`と`CPU負荷`を比較してみます。

## 文字の説明
###　Meta Char
| 記号 | 説明 | 例 |
|-----|-----|-----|
| ^ | 文字列の始まり | *^regExp* は文字列の最初にregExpがある場合マッチする |
| [^] | 一致しない (NOT) | *[^regExp]* はregExpではない場合マッチする |
| $ | 文字列の終わり | *regExp$* は文字列がregExpで終わる場合マッチする |
| \b | 単語の境界（空白・カンマ・タブなど） | *\bso\b* は *why so serious?*という文字列に　*so* にマッチする |
| \B | 単語の境界（空白・カンマ・タブなど）以外 | *\Bo\B* は *hello world* という文字列に　*worldの o*にマッチする |
| \s | 空白 | 空白及びタブがある場合にマッチする |
| \S | 空白以外 | 空白及びタブがない場合にマッチする |
| \d | 数字 | [0-9]と同じ意味で数字にマッチする |
| \D | 数字以外 | [^0-9]と同じ意味で数字ではない文字列にマッチする |
| \w | 単語に使用される文字（アルファベット、数字、_ ） | [a-zA-Z_0-9]と同じ意味でアルファベット、数字、_  が入っている文字列にマッチする |
| \W | 単語に使用される文字（アルファベット、数字、_ ）以外| [^a-zA-Z_0-9]と同じ意味で*記号* などアルファベット、数字、_  がない文字列にマッチする |
| \記号 | エスケープを表す | \\.　 \\*　\$ など記号にマッチする |
| . | 文字1つ | *n.* の場合 no・niなどnの後ろになんでも1つの文字が入ればマッチする |

###　選択パターン
| 記号 | 説明 | 例 |
|-----|-----|-----|
| &#124; | OR | *A&#124;B* の場合 AやBにマッチする |
| [ ] | [ ]なかの文字の中一つ | *[oik]oho* の場合 oohoやioho、kohoにマッチする |
| [ - ] | 範囲 | *[0-9]*の場合 0から9にマッチする |

###　量指定子
| 記号 | 説明 | 例 |
|-----|-----|-----|
| ? | 前の部分があるかもないかも | *Qiita?* の場合 Qiita、Qiitどっちにもマッチする |
| * | 前の部分が0個以上 | *n\d** の場合 n、n1、n12などにマッチする |
| + | 前の部分が1個以上 | *n\d+* の場合 *n\d** とは違ってn以外の文字列にマッチする |
| {n} | n個ある | *n\d{3}* の場合 n125みたいに数字が3つある文字列にマッチする |
| {n, m} | n個以上、m個以下 | *n\d{1, 2}* の場合 n5やn12みたいに数字が1つから2つある文字列にマッチする |
| {n,} | n個以上 | *n\d{3,}* の場合 n15487みたいに数字が3つ以上ある文字列にマッチする |
※大文字と小文字はお互い逆の意味になる

### グループ
`()`で表現する。グループを使うと下記のような書き方ができる

```
(to)ma\1　→　tomato

# (to) = グループでtoを意味
# ma = ma
# \1 = グループ1番の 'to'を意味
```


## よく使う正規表現パターン
### 1. 数字だけ
```
^[\d]+$

OR

^[0-9]+$
```

### 2. 数字、アルファベットだけ
```
^[a-zA-Z\d]+$
```

### 3. URL
```
^https?:\/\/([a-z0-9-]+\.)+[a-z0-9]{2,4}.*$
```

### 4. 電話番号 (000-0000-0000)
```
(\d{3}).*(\d{4}).*(\d{4})
```

### 5. メールアドレス
```
([\w\.\/\-]+)@([\w_\/\-]+)\.([\w_\.\/\-]*)[a-z][a-z]
```

### 6. 画像ファイル (jpg, png, gif)
```
([^\s]+(?=\.(jpg|gif|png))\.\2)
```

# 書き方のによる実行時間・CPU負荷比較

### 検証前提
比較の検証はVBScriptで実装したコードを基に行っています。

### 検証コード
```vb:CompareRegexpPattern.vb
Dim timerStart, timerEnd
Dim result, loopcount
Dim intExText: intExText = "000-5587-9999"
Dim addressEx: addressEx = "aaa7548_aaaa@qiita.com"
Dim cpuName, cpuClock, cpuLoadPercentage
Dim loopCountHalf

loopCount = 10000
loopCountHalf = loopCount / 2

Call GetCPUInfo(cpuName, cpuClock, cpuLoadPercentage)
wscript.echo "CPU Name : " & cpuName
wscript.echo "CPU Clock : " & cpuClock
wscript.echo "CPU Load PCT : " & cpuLoadPercentage
wscript.echo vbCrLf 

' /////////////////////////////////
' CellNumber regExp Use Pure Char
' ////////////////////////////////
timerStart = CDbl(Timer)
For i = 0 To (loopCount - 1)
    result = ExecuteRegExp("cellNumber", "pure", intExText, i)
Next
timerEnd = CDbl(Timer)
wscript.echo "CellNumber/Pure Char : " & (timerEnd - timerStart)
wscript.echo "CPU Load PCT : " & cpuLoadPercentage
wscript.echo vbCrLf 

' /////////////////////////////////
' CellNumber regExp Use Meta Char
' ////////////////////////////////
timerStart = CDbl(Timer)
 For i = 0 To (loopCount - 1)
    result = ExecuteRegExp("cellNumber", "meta", intExText, i)
Next
timerEnd = CDbl(Timer)
wscript.echo "CellNumber/Meta Char : " & (timerEnd - timerStart)
wscript.echo "CPU Load PCT : " & cpuLoadPercentage
wscript.echo vbCrLf 

' /////////////////////////////////
' Address regExp Use Pure Char
' ////////////////////////////////
timerStart = CDbl(Timer)
 For i = 0 To (loopCount - 1)
    result = ExecuteRegExp("address", "pure", addressEx, i)
Next
timerEnd = CDbl(Timer)
wscript.echo "Address/Pure Char : " & (timerEnd - timerStart)
wscript.echo "CPU Load PCT : " & cpuLoadPercentage
wscript.echo vbCrLf 

' /////////////////////////////////
' Address regExp Use Meta Char
' ////////////////////////////////
timerStart = CDbl(Timer)
 For i = 0 To (loopCount - 1)
    result = ExecuteRegExp("address", "meta", addressEx, i)
Next
timerEnd = CDbl(Timer)
wscript.echo "Address/Meta Char : " & (timerEnd - timerStart)
wscript.echo "CPU Load PCT : " & cpuLoadPercentage

' /////////////////////////////////
' Def Funciton
' /////////////////////////////////
Function ExecuteRegExp(regExpPattern, charExpression, text, loopCount)
    ExecuteRegExp = False

    Dim regExpObject
    Set regExpObject = New RegExp
    With regExpObject
        .Global = True
        .IgnoreCase = True
    End With
    
    If Not ExecuteRegExp Then
        If regExpPattern = "cellNumber" Then
            ' 電話番号の正規表現パターン
            If charExpression = "meta" Then
                regExpObject.Pattern = "(\d{3}).*(\d{4}).*(\d{4})"
            Else
                regExpObject.Pattern = "([0-9]{3}).*([0-9]{4}).*([0-9]{4})"
            End If
        ElseIf regExpPattern = "address" Then
            ' メールアドレスの正規表現パターン
            If charExpression = "meta" Then
                regExpObject.Pattern = "([\w\.\/\-]+)@([\w_\/\-]+)\.([\w\_\.\/\-]*)[a-z][a-z]"
            Else
                regExpObject.Pattern = "^\b[a-zA-Z0-9\.\_\%\+\-]+@[a-zA-Z0-9\_\.\/\-]+\.[a-zA-Z]{2,4}\b$"
            End If
        End If

        ExecuteRegExp = regExpObject.Test(Trim(text))
        ' CPU
        If loopCount = loopCountHalf Then
            Call GetCPUInfo(cpuName, cpuClock, cpuLoadPercentage)
        End If
    End If

    Set regExpObject = Nothing
End Function

' Get CPU Load
Function GetCPUInfo(cpuName, cpuClock, cpuLoadPercentage)
    Dim oClassSet, oClass, oLocator, oService
    Dim szMsg

    Set oLocator = WScript.CreateObject("WbemScripting.SWbemLocator")
    Set oService = oLocator.ConnectServer
    Set oClassSet = oService.ExecQuery("SELECT * FROM Win32_Processor")
    For Each oClass In oClassSet
        cpuName = oClass.Name
        cpuClock = oClass.CurrentClockSpeed
        cpuLoadPercentage = oClass.LoadPercentage
    Next

    Set oClassSet = Nothing
    Set oClass = Nothing
    Set oService = Nothing
    Set oLocator = Nothing
End Function
```

### 検証結果
CPU Name : CPU名
CPU Clock : CPUクロック
CPU Load PCT : CPU負荷
RegExp Function/使用したChar : 実行時間
![regexp.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439677/126b2fe6-e281-5b8f-1928-9905ad1e64dc.jpeg)

上記で、大して大きくはないが `Meta Char`の方が実行時間が早いという結果が得られました。


## 正規表現のパターンチェック
https://rubular.com/r/iwa8piuR5r

## 参照元
韓国の資料を基に作成しました。
https://soooprmx.com/archives/7718