正規表現のすすめ〜ノンプログラマーでも覚えておきたい正規表現の基本〜

GAS
この記事は約8分で読めます。

今回はノンプログラマーのための正規表現の入門編をまとめていきたいと思います。

利用する環境はGASとpython(python3.8)です。このブログでよく使ってる2つの環境を対象に説明していきます。

GASやpythonはやらないから関係ないという人も実は触れる機会があるって知ってました?

実は、みなさん大好きエクセルでも実はコンテンツ検索を行う時にワイルドカードを用いた正規表現の部分利用が可能です。

検索でワイルドカード文字を使用する
テキストフィルターの比較条件としてワイルドカード文字を使用したり、コンテンツの検索と置換を行ったりします。 この機能により、単純なパターンを共有する値を見つけることができます。 これらの文字には、アスタリスク (*)、疑問符 (?)、チルダ (~) を使うことができます。

エクセルでも使えると思えば、汎用的に読んでもらえるのかな?w
VBAでRegExpを利用する方法もあるみたいですが、私はVBA苦手人間なので、今回はVBA環境は割愛しています。

まぁそれはさておき、正規表現についてみていきます。

Advertisements

正規表現とは?

そもそも正規表現とはなんでしょうか?

wikipediaによると以下のように定義されていました。

正規表現(せいきひょうげん、英: regular expression)とは、文字列の集合を一つの文字列で表現する方法の一つである

https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE

よくわかるようなわからないようなw 足りてるような足りてないような。

個人的には、特定の文字列をメタキャラクタという特定の文字や記号を使って、汎用的な1つの文字列に置き換える表現方法かなと思ってます。

なぜ正規表現が便利なのか?

定義だけ聞いても何が便利なのかわからない人に簡単なサンプルです。

例えば以下のようなユーザの情報に電話番号のカラムがあり、ただ携帯番号と固定電話が混ざっていたとします。ここの中から携帯電話の番号だけ抽出して欲しいと言われたらどうしますか?

正直このケースはデータが20件なので、目視でチェックして確認するよってのもの一つの手です。

ただ、これが100件だったら?1000件だったら?ユーザの多いサービスならゆうに数万件の中から探してって言われたら?

目視は限界がありますよね。

じゃぁプログラミングでやろう、ってなるのですが、ここでパッと思いつくのが、携帯番号だから、条件分岐で抽出することを考えるのですかね。

どんな条件か考えてみましょう。

  • ・070~090で始まる数値
  • ・4つ目または9つ目が”-“のもの
  • ・桁数が11桁のもの(固定電話は10桁、携帯電話は11桁ですよね)

あれっ実は桁数でいけば、正規表現使わなくてもいけちゃいそうですね。まぁでも上の2つを利用する場合、正規表現が便利になります。

抽出条件純粋条件分岐正規表現
070~090で始まる数値070 or 080 or 0900[789]0
4つ目または9つ目が”-“のものif str[3] == “-“

if str[10] == “-“
\d{3}-
条件分岐と正規表現での違い

だいぶ省略してかけますよね。それに汎用性がある。ということで、便利ってなります。

実際は正規表現は数値検索で利用というよりは、文字列検索で最も力を発揮します。例えばgmailやgoogle documentなどの文中やタイトルの検索など。これはあくまでサンプルなのでお許しください

正規表現の使い方

GASでの使用方法

GASではnew RegExp()でイニシャライズさせる方法と、下記のように直接正規表現を/ *** /(スラッシュ二つ)で囲って正規表現を作成する方法の2通りがあります。

function myFunction() {
  let list = [
    "090-1111-2222", "0587-11-2222", "0120-03-2457", "070-4444-2222", "080-1111-2222"
];

  let regex = /0[789]0-\d{4}-\d{4}/;
  
  //listから抽出
  for(let x of list){
    if(x.match(regex)){
       Logger.log(x);
       }
  }
    
}

let regexで正規表現を指定して、for文でlistの要素を一つづつ抽出し、match(regex)で一致するかどうかを検証しています。

pythonでの使用方法

pythonで正規表現を使う方法をみていきます。例題として、リストのデータから正規表現で該当データを取得する方法と、文字列から正規表現で該当データを取得する方法です。

import re

list = [
    "090-1111-2222", "0587-11-2222", "0120-03-2457", "070-4444-2222", "080-1111-2222"
]

text = "090-1111-2222, 0587-11-2222, 0120-03-2457, 070-4444-2222, 080-1111-2222"


regex = re.compile(r'0[789]0-\d{4}-\d{4}')
pickup =[]
for item in list:
    if regex.match(item):
        pickup.append(*regex.findall(item))
print("listからpickup:",pickup)


pickup2 = regex.findall(text)
print("文字列からpickup:", pickup2)

基本的な正規表現

基本的な正規表現のパターンをメジャーなものに限りですがピックアップして紹介していきます。軽く辞書っぽくなりますが、ご容赦ください。

文字概要正規表現のサンプルマッチする文字列の例
.任意の1文字 にマッチ.A

1
+直前の文字が 1回以上 繰り返す場合にマッチ
最長一致(条件に合う最長の部分に一致)
Ap+leAple
Apple
Appple
Apppple
*直前の文字が 0回以上 繰り返す場合にマッチ
最長一致(条件に合う最長の部分に一致)
Ap*leAle
Aple
Apple
Appple
?直前の文字が 0個か1個 の場合にマッチ
最長一致(条件に合う最長の部分に一致)
Ap?leAle
Aple
+?直前の文字が 1回以上 繰り返す場合にマッチ
最短一致(条件に合う最短の部分に一致)
Ap+?leAple
Apple
Appple
Apppple
*?直前の文字が 0回以上 繰り返す場合にマッチ
最短一致(条件に合う最短の部分に一致)
Ap*?leAle
Aple
Apple
Appple
|OR条件App(le | el)Apple
Appel
[…]角カッコに含まれるいずれか1文字0[7,8,9]0
0[7-9]0
070, 080, 090
[^…]角カッコに含まれる文字以外にマッチ0[^0-6]0070, 080 ,090, 0a0, 0b0…
0-6以外の文字
{n}直前の文字の桁数を指定1{3}
a{3}
111
aaa
{n, }直前の文字の最小桁数のみ指定1{3, }
a{3, }
111
1111
11111….
aaa
aaaa
aaaaa….
{n, m}直前の文字の最小桁数と最大桁数を指定
最長一致(条件に合う最長の部分に一致)
a{3,4}aaa
aaaa
{n, m}?直前の文字の最小桁数と最大桁数を指定
最短一致(条件に合う最長の部分に一致)
a{3,4}?aaa
aaaa
基本的な正規表現

次に正規表現で予め定義されている正規表現を紹介します。数字・文字・タブ・改行などについて、正規表現で予め定義されているものがあります。

文字概要正規表現のサンプルマッチする文字列の例
\tタブ\tタブがある場合
\r改行 CR(Carriage Return)\rCR改行
\n改行 LF(Line Feed)\nLF改行
\dすべての数字
[0-9]と同じ意味
\d{3}000 ~ 999
\Dすべての数字以外の文字
[^0-9]と同じ意味
\D{3}aaa
あああ etc
\wアルファベット、アンダーバー、数字
[a-zA-Z_0-9]と同じ意味
^https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$urlの場合
(http, httpsの両方)
\Wアルファベット、アンダーバー、数字以外の文字
[^a-zA-Z_0-9]と同じ意味
\W
\s空白文字。半角スペース、タブ、改行文字のいずれか
全角スペースは対象外
\s
定義されている正規表現

多用する正規表現

頻繁に利用する正規表現は毎回考えるのがめんどくさいので、一覧として持っておくと良いと思います。

対象正規表現
メールアドレス^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
URL(httpの場合も含む)^https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
ドメイン^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z-]{2,}$
携帯電話番号^0[789]0-\d{4}-\d{4}$
固定電話番号^0\d(-\d{4}|\d-\d{3}|\d\d-\d\d|\d{3}-\d)-\d{4}$
日付(YYYY-MM-DD)^\d{4}-\d{2}-\d{2}$
郵便番号^\d{3}-\d{4}$
多用する正規表現

まとめ

正規表現について見てきました。

正規表現はこれだけで何かができるというわけではないのですが、プログラミングにおける基礎の部分(土台というニュアンスで)だと思っています。

算数で四則演算をみんながマスターして日常生活が楽になるように、プログラミングにおいて正規表現ができるようになるといろんな局面で役にたつなと。

パターンが多く、全てを説明していませんが、正規表現に関する本もありますし、ブログにも多く紹介されていたりもしますので、是非習得してもらえればと思います。

コメント