【初学者向け】使いこなせ......正規表現っ........!!

## 対象
この記事はエンジニア初学者の方に向けて記載しております。

## はじめに
正規表現、勉強していますか？

特にエンジニア初学者の方は、初めての現場参画に向けて、
**「言語の勉強はバッチリだぜッ！」**
と意気込んでいても、正規表現の学習は疎かにしてしまい、
現場で **「くぁwせdrftgyふじこlp...」** となった方も多いかと思います。
※自分もそうでした。。。

私自身、エンジニアとして3年程経過しているのですが、
現場で働くにおいて、**正規表現の知識は必須**といっても過言ではありません。

もし正規表現を使わなければ、1.2時間かかる調査や作業も、
**正規表現を使えば、1分で解決できちゃったりもします。**

この記事を通して、
現場で使われる正規表現の活用法をしっかりとマスターしていただければと思います！


## 流れ
[・そもそも正規表現とは](#そもそも正規表現とは)
[・まずは覚える。](#まずは覚える)
[・業務で使われる正規表現にチャレンジ！](#業務で使われる正規表現にチャレンジ)


### ■そもそも正規表現とは
**文字列のパターンを指定して、検索や置換を行う**際に使用される表記法です。
正規表現を使えばこんなことができます。

**例1)**
11桁の連続する数値を「3桁-4桁-4桁」に置換(検索)
```
56898176288
09307215360
54873905721
↓
568-9817-6288
093-0721-5360
548-7390-5721
```

<details>
  <summary>※正規表現：</summary>

・置換(検索)対象文字列：(\d{3})(\d{4})(\d{4})
・置換後文字列：\\$1-\\$2-\\$3
</details>


**例2)**
文字「world」の内、**直前が「Hello」ではない「world」のみ**「Japan」に置換(検索)

```
Hello world
Welcome to world
Go to world
↓
Hello world
Welcome to Japan
Go to Japan
```

<details>
  <summary>※正規表現：</summary>

・置換(検索)対象文字列：(?<!Hello )world
・置換後文字列：Japan
</details>


### ■まずは覚える。
覚えることはそんなに多くありません！
下記サイトに綺麗にまとまっています。
1日あれば覚えられる量なのでささっと覚えちゃいましょう！
https://troutlurefishing.jp/regex.htm

サイトの内、下記だけ覚えれば十分です。
**・基本的な正規表現**
★これだけは全部おぼえましょう！

**・定義済みの正規表現（下記だけ）**
\t：タブ
\d：すべての数字
\w：英字、＿、数字

**・特定の位置関係の正規表現（下記だけ）**
^：直後の文字が行の 先頭 にある場合にマッチ
$：直前の文字が行の 末尾 にある場合にマッチ

**・置換後文字列で使える正規表現（下記だけ）**
\1 ～ \9：一致文字列の1～9番目の文字列に置換

**＋α**
**・先読み・後読み**
(?=pattern)：直後にpatternの文字列がある（肯定先読み）
(?!pattern)：直後にpatternの文字列が無い（否定先読み）
(?<=pattern)：直前にpatternの文字列がある（肯定後読み）
(?<!pattern)：直前にpatternの文字列が無い（否定後読み）

※下記のサイトに詳しくまとまっています。
[先読みと後読みを使ったパターン](https://www.javadrive.jp/regex-basic/writing/index2.html)


### ■業務で使われる正規表現にチャレンジ！
ここまでで使える手札はそろいました！
いざ業務で使われる正規表現にチャレンジしてみましょう！


#### 問題１

下記のテキストの「@」以降の文字を抽出して下さい。

```
TOKC36JWGKCH@docomo.ne.jp
HJK2KQY7CNAG@docomo.ne.jp
DM4MEAVV5HHL@excite.co.jp
P2ZOWMZP5BUY@me.com
AKHEI4LRKDK6@outlook.jp
HM8FFMQ8XHDA@yahoo.ne.jp
TT1ZKBT3KESW@ymobile.ne.jp
```
<details>
  <summary>解答：</summary>

  ・置換対象文字列：^\w+@(.\*)$
  ・置換後文字列：\\$1

```
docomo.ne.jp
docomo.ne.jp
excite.co.jp
me.com
outlook.jp
yahoo.ne.jp
ymobile.ne.jp
```
</details>



#### 問題２
下記のテキストの「A-B-C」を
「['name' => 'A', 'age' => 'B', 'gender' => 'C'],」
という表記に置換して下さい。

```
sazae-23-female
katsuo-11-male
wakame-9-female
namihei-54-male
fune-48-female
masuo-32-male
tarao-3-male
tama-1-male
norisuke-26-male
taiko-22-female
ikura-1-male
```
<details>
  <summary>解答：</summary>

  
  ・置換対象文字列：^(\w+)-(\d+)-(\w+)\$
  ・置換後文字列：['name' => '\\$1', 'age' => '\\$2', 'gender' => '\\$3'],
  
```
['name' => 'sazae', 'age' => '23', 'gender' => 'female'],
['name' => 'katsuo', 'age' => '11', 'gender' => 'male'],
['name' => 'wakame', 'age' => '9', 'gender' => 'female'],
['name' => 'namihei', 'age' => '54', 'gender' => 'male'],
['name' => 'fune', 'age' => '48', 'gender' => 'female'],
['name' => 'masuo', 'age' => '32', 'gender' => 'male'],
['name' => 'tarao', 'age' => '3', 'gender' => 'male'],
['name' => 'tama', 'age' => '1', 'gender' => 'male'],
['name' => 'norisuke', 'age' => '26', 'gender' => 'male'],
['name' => 'taiko', 'age' => '22', 'gender' => 'female'],
['name' => 'ikura', 'age' => '1', 'gender' => 'male'],
```
</details>


#### 問題３
下記のテキストの内、
「INSERT INTO scores...」もしくは「UPDATE scores...」
から始まる行を抽出し、それ以外の行は削除して下さい。
※1回の正規表現の置換のみでは難しいかと思うので、
置換を何回か繰り返して抽出してみてください！

```
INSERT INTO tests (id, name, date_of_implementation) VALUES ...
UPDATE scores SET name = ...
INSERT INTO users (id, name, gender) VALUES ...
UPDATE tests SET name = ...
UPDATE tests SET name = ...
UPDATE tests SET name = ...
INSERT INTO users (id, name, gender) VALUES ...
INSERT INTO tests (id, name, date_of_implementation) VALUES ...
UPDATE tests SET name = ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
INSERT INTO tests (id, name, date_of_implementation) VALUES ...
INSERT INTO users (id, name, gender) VALUES ...
INSERT INTO tests (id, name, date_of_implementation) VALUES ...
UPDATE scores SET name = ...
UPDATE tests SET name = ...
UPDATE users SET name = ...
UPDATE tests SET name = ...
UPDATE users SET name = ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
UPDATE users SET name = ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
```

<details>
  <summary>解答：</summary>

※あくまで解答例となります。
他にもよい方法があればコメントで教えてください！

解答例）
**対象行の先頭に「★」を付ける**
    ・置換対象文字列：^(INSERT INTO |UPDATE )(?=scores)
    ・置換後文字列：★\\$1
↓
**対象行以外（先頭が「★」以外）の行を空行に置換**
・置換対象文字列：^[^★].*$
・置換後文字列：（空欄）
↓
**空行の削除**
・置換対象文字列：^\r\n
・置換後文字列：（空欄）
↓
**対象行の「★」の削除**
・置換対象文字列：★
・置換後文字列：（空欄）

※別解）
[@Silver_of_999](https://qiita.com/Silver_of_999)さんより、下記方法を使えば、
一発で置換できるとの方法をコメント頂きました。（ありがとうございます！！）
・置換対象文字列：^(?!(INSERT INTO|UPDATE) scores).+\r\n
・置換後文字列：（空欄）

```
UPDATE scores SET name = ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
UPDATE scores SET name = ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
INSERT INTO scores (id, user_id, test_id, score) VALUES ...
```
</details>

## さいごに
いかがでしたでしょうか？
私自身、正規表現を初めて学習したときに、
**「こんな便利な機能があるのか！？」** と感動したのを覚えています。
この記事が、少しでも初学者の方の手助けになれれば幸いです。