正規表現が苦手な人、お集まりください。

# はじめに
あなたは正規表現は得意ですか？？
「はい、得意です！」と答える人は、そんなに多くないのかな？と思います。
自分は特に苦手で嫌いでした。。
このままではダメだと思い、正規表現の壁に立ち向かいました。
自分がもがいて手に入れた情報で、皆さんに少しでもいい情報を届けたれたら幸いです！！

`※一番下に、正規表現に用いる記号一覧を載せてあるので参考にしてください！`

# 正規表現とは
文字列とのパターンマッチを行うための小さな言語のことです。
正規表現を用いることで、ある文字列があるパターンに該当する文字列を含んでいるかを確認したり、パターンに該当する部分を検索できます。

## パターンマッチ（Ruby）
### Regexp#=~
正規表現にマッチした位置を返すときは、`=~`を使用する

```ruby
# マッチしたら、その位置を返す
/[0-9]/ =~ 'ruby6' #=> 4

# マッチしない場合はnilを返す
/[0-9]/ =~ 'ruby' #=> nil
```

### Regexp#===
あるパターンにマッチするかを調べるには、`===`を使用する

```ruby
# 0〜9の数字を含んでいるか
/[0-9]/ === 'ruby' #=> false
/[0-9]/ === 'ruby6' #=> true
```

### Regexp#match
マッチすればMatchDataオブジェクトを返し、しなければ「nilを返す

```ruby
str = 'ruby6'

if matched = /[0-9]/.match(str)
  p matched #=> "#<MatchData \"6"\>"
end
```

MatchDataから得られる情報は以下の通りです。

| MatchData | 変数 | 得られる値 |
|:-:|:-:|:-:|
| MatchData#[0]  | $&  | 直前にマッチした文字列  |
| MatchData#[1]  | $1  | 直前にマッチした正規表現の中の、最初の括弧にマッチした文字列  |
| MatchData#pre_match  | $`  | 直前にマッチした文字列より前の文字列  |
| MatchData#post_match  | $'  | 直前にマッチした文字列より後の文字列  |

## 式展開時の注意点
正規表現で、式展開を用いる際は必要に応じてエスケープしましょう！

```ruby
# エスケープする必要のある文字列
part = Regexp.escape('(incomplete)')
/[^.]+#{part}\.txt/ #=> /[^.]+\(incomplete\)\.txt/ # 括弧がエスケープされる
```

## 文字クラス
`[]`で囲むことで文字クラスの指定が可能です。

```ruby
[a-z] #=> aからzまでの文字

[\w] #=> 英数字a(A)～z(Z)、0～9
```

## 量指定子
直前パターンの繰り返しをします。

```Ruby
# 郵便番号の正規表現の場合
post_num = /\d{3}-\d{4}/
post_num === '123-4567' #=> true
```

## 先頭と末尾
先頭には`\A`、末尾には`\z`として表現する。

```ruby
# 携帯電話番号の正規表現の場合
phone_num = /\A\d{3}-\d{4}-\d{4}\z/
phone_num === '012-3456-7890' #=> true
```

## 指定位置からの正規表現
指定された文字列 str に対して 位置 pos から自身が表す正規表現によるマッチ

```ruby
/R.../.match?("Ruby")    #=> true
/R.../.match?("Ruby", 1) #=> false
$&                       #=> nil
```

## グルーピングと後方参照
`()`によりグルーピングをすることが可能。
後で、`\1`や`\2`のように参照することを後方参照と言います。

```ruby
# 基本的な後方参照
/(text)\ to\ \1/ === 'text to text' #=> true

# ラベル付きグルーピングでの後方参照
/(?<num>[0-9+])[a-c\-]+\k<num>/ === '123-abc-123' #=> true
```

### 部分式呼び出し
後方参照と似ているが、グルーピングを再利用できる`部分式呼び出し`という参照方法がある。

```ruby
# 部分式呼び出しの「\g<1>」は最初のグルーピングの式「[0-9+]」で置換される
/([0-9+])-\g<1>-\g<1>/ === '012-3456-7890' #=> true
```

## 先読みと後読み
先読みとは、`(?<=sample)`は「"sample"という文字列と一致する箇所の直後」を表します。
また、後読みはその逆で直前になります。
また、否定文に関しては、文字通り肯定先(後)読みと逆の動作をします。

```ruby
# 肯定先読み
'sampleApp'.scan(/sample(?=App)/) #=> ["sample"]

# 肯定後読み
'sampleApp'.scan(/(?<=sample)App/) #=> ["App"]
```

## バックトラックの抑止
`(?>)`で正規表現を囲むことで、そこにマッチした部分でバックトラックを抑止できる。

```ruby
/(?>\w+)[0-9]/ === 'ruby6' #=> false
```

## オプションの指定
以下の表を用いて、オプションを指定することでパターンマッチの挙動を変化させることが出来ます。

| オプション | 意味 |
|:-:|:-:|
| i  | 大文字、小文字の区別をしない  |
| o  | 正規表現リテラルが最初に評価された際に、一度だけ式展開を行う  |
| x  | 正規表現中の「#」を無視して、コメントとみなす  |
| m  | 「.」に改行もマッチさせる、複数行モード  |
| u  | 正規表現をUTF-8として解釈  |
| s  | 正規表現をShift-JISとして解釈  |
| e  | 正規表現をEUC-JPとして解釈  |
| n  | 正規表現をASXIIとして解釈  |

```ruby
# オプション無し
%w(foo bar).map { |str| /#{str}/ } #=> [/foo/, /bar/]

# オプション有り
%w(foo bar).map { |str| /#{str}/o } #=> [/foo/, /foo/]
```

# 終わりに
正規表現は必ずと言っていいほど、最初はハマります。。
暗号のように見えてきて気が狂いそうですが、この記事を機に慣れていってくれることを願っています！

## 宣伝
想像以上の反響をいただき、ありがとうございます！！
よかったら、[自分のTwitter](https://twitter.com/output_program)でも、有益な情報を発信していますので、興味があればフォローしていただけると嬉しいです！

# 参考(正規表現に用いる記号一覧)
| 1 | 2 |
|:-:|:-:|
| ^  | 行頭、改行文字の直後にマッチ  |
| $  | 行末、改行文字の直前にマッチ  |
| \A  | 文字列の先頭にマッチ  |
| \Z  | 文字列の末尾にマッチ、改行文字なら改行の直前  |
| \z  | 文字列の末尾にマッチ、改行でも常に末尾にマッチ  |
| \w  | 英数字[0-9A-Za-z_]にマッチ  |
| \W  | 英数字[0-9A-Za-z_]以外にマッチ  |
| \s  | 空白文字[\t\r\n\f]にマッチ  |
| \S  | 空白文字[\t\r\n\f]以外にマッチ  |
| \d  | 数字[0-9]にマッチ  |
| \D  | 数字[0-9]以外にマッチ  |
| \h  | 16進数に使われる文字[0-9A-Fa-f]にマッチ  |
| \b  | []の外では単語の境界、中ではバックスペースにマッチ  |
| \B  | 単語の境界以外にマッチ  |
| \G  | 直前にマッチした箇所の直後にマッチ  |
| .  | 改行を除く任意の1文字にマッチ  |
| []  | 文字クラスの指定  |
| [0-9]  | すべての数字にマッチ  |
| [^0-9]  | すべての数字以外にマッチ  |
| *  | 直前の正規表現の0回以上の反復、できるだけ長くマッチ  |
| +  | 直前の正規表現の1回以上の反復、できるだけ長くマッチ  |
| *?  | 直前の正規表現の0回以上の反復、より短くマッチ  |
| +?  | 直前の正規表現の1回以上の反復、より短くマッチ  |
| ?  | 直前の正規表現の0〜1回の反復  |
| ??  | 直前の正規表現の0〜1回の反復、より短くマッチ  |
| {m}  | 直前の正規表現のm回の反復   |
| {m}?  | 直前の正規表現のm回の反復、より短くマッチ   |
| {m,}  | 直前の正規表現のm回以上の反復   |
| {m,}?  | 直前の正規表現のm回以上の反復、より短くマッチ   |
| {m,n}  | 直前の正規表現のm〜n回の反復  |
| {m,n}?  | 直前の正規表現のm〜n回の反復、より短くマッチ   |
| ()  | グループ化  |
| \n  | 後方参照、正規表現のn番目のグループにマッチした文字列にマッチ  |
| \k< label name >  | 後方参照、ラベルでマッチ  |
| (?:)  | グループ化、後から参照出来ない  |
| (?< label name >)  | ラベル付きグループ化  |
| (?#)  | コメント  |
| (?=)  | 先読み  |
| (?!)  | 否定先読み |
| (?<=)  | 後読み  |
| (?<!)  | 否定後読み  |
| (?>)  | バックトラック抑止  |
| (?ixm-ixm)  | オプションのon/off  |
| (?ixm-ixm:)  | 括弧内のオプションのon/off  |
| a &#124; b  | aもしくはbにマッチ|