こんにちはー。今回は「正規表現」について解説します。
聞いたことがある方もいるかもしれませんが、正規表現とは何か、どのように使うのか、わかりやすく説明していきます。
これを読んで正規表現の基礎を理解していただけるように書いたのでぜひ最後まで読んでくださると嬉しいです。
正規表現とは?
正規表現(Regular Expression、略してRegex)は、特定の文字列のパターンを検索、マッチング、置換するための強力なツールです。プログラミングやテキスト処理の際に使われ、例えばメールアドレスや電話番号の形式を確認したり、特定の単語を検索・置換したりすることができます。
#include<iostream> int main(){ std::cout << "正規表現を学ぼう" << std::endl; }
上記のC++ソースコードについて考えていきます。
このプログラムの中には”std”という文字列があります。これを正規表現で表すと、そのままstdとなります。まあ、これは当たり前です。全ての単語が一致していますので検索にstdと入力すれば、2箇所のstdが選ばれます(std::coutとstd::endl)。
このようなことを、正規表現’std’は文字列”std”にマッチするといいます。
えっ、正規表現って調べたい単語そのものってこと?と思われた方もいるのではないでしょうか。
次は以下のプログラムを考えます。
#include<iostream> int main(){ std::cout < "これはどうだ!\n"; //これがコメント }
このプログラムのコメント部分にマッチさせてください。コメントなので、正解は「//これがコメント」になります。
しかし、任意の「//」によるコメントにマッチさせる場合、「//これがコメント」という正規表現ではダメです。コメントの内容によってマッチしなくなってしまいます。
どんな内容のコメントでもマッチさせるためにメタ文字と呼ばれる文字が使われます。次の章ではメタ文字を学習していきます。
メタ文字〜任意の文字列にマッチさせる方法〜
メタ文字は特別な意味を持つ文字です。メタ文字は以下の種類があります。
メタ文字 | 意味 | 例 |
. (ドット) | 任意の1文字にマッチする | c.t は “cat”、”cot”、”cut” などにマッチする |
^ (キャレット) | 行の先頭にマッチする | ^cat は “cat” で始まる行にマッチする |
$ (ドル) | 行の末尾にマッチする | cat$ は “cat” で終わる行にマッチする |
ドット(.)はよく使います。任意の1文字になるので、a,b,…,y,z、A,B,…,Y,Zなど様々なパターンにマッチします。
kで始まる単語かつ2文字の単語にマッチさせたいときは、k.
にします。3文字で真ん中(2文字目)がuの単語にマッチさせたいときは、.u.
です。任意の1文字+u+任意の1文字で検索できます。
しかし、aで始まる10文字の単語にマッチさせるときはどうでしょうか。a.........
でできますが、ドットをたくさん使うとわかりにくいです。それに、文字数が具体的にわからないと現状ではマッチさせることができません。
そこで繰り返しの意味をもつ文字を使用します。
メタ文字 | 意味 | 例 |
* | 0回以上の繰り返し | a* は “”、”a”、”aa”、”aaa” などにマッチします。 |
+ | 1回以上の繰り返し | a+ は “a”、”aa”、”aaa” などにマッチします |
? | 0回または1回の出現 | a? は “” または “a” にマッチします |
{n} | 正確に n 回の繰り返し | a{3} は “aaa” にマッチします |
{n,} | 少なくとも n 回の繰り返し | a{2,} は “aa”、”aaa”、”aaaa” などにマッチします |
{n,m} | n 回から m 回の繰り返し | a{2,4} は “aa”、”aaa”、”aaaa” にマッチします |
これらは繰り返しを表す文字です。先ほどの、aで始まる10文字の単語にマッチさせるときをもう一度考えてみましょう。
今回、任意の文字列がaの後ろで9回繰り返されると言い換えられます。よって、正規表現はa.{9}
になります。
aで始まる5から10文字の単語にもマッチしてみましょう。範囲を指定した繰り返しは{min, max}
で表現できます。よって、a.{5, 10}
になります。
次は、”cat”, “cot”, “cut”のみにマッチさせる方法を考えます。c.t
ではドット(.)が任意の1文字であることから、この三つ意外の単語にもマッチしてしまいます。
そこで登場するのが文字クラスです。
メタ文字 | 意味 | 例 |
[(文字)(文字)… ] | [ ]の中にある文字にマッチするかどうか | [abc] は “a”、”b”、”c” のいずれかにマッチします |
[(整数)-(整数)] | [(整数1)-(整数2)]は(整数1)から(整数2)までの数字にマッチするかどうか | [0-9] は任意の数字(0から9)にマッチします |
[(小文字)-(小文字)] | [(小文字1)-(小文字2)]はアルファベット1からアルファベット2までのどれかにマッチするかどうか | [a-z] は小文字のアルファベット全てにマッチします |
[(大文字)-(大文字)] | [(大文字1)-(大文字2)]はアルファベット1からアルファベット2までのどれかにマッチするかどうか | [A-Z] は大文字のアルファベット全てにマッチします |
[^(文字)…] | ^の後ろにある文字以外でマッチするかどうか | [^abc] は “a”、”b”、”c” 以外の任意の文字にマッチします。 |
これを使うことで、c[aou]t
は”cat”, “cot”, “cut”のみにマッチさせることができます。
[a, o, u]
ではないことに注意してください。コンマ(,)は必要ありません。
実際の使い方
基本的な正規表現について学習しました。
ここからは、正規表現を使った具体的な例を見ていきましょう。
メールアドレスの検証
メールアドレスの形式が正しいかどうかを確認するには、以下のような正規表現を使います。
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
この正規表現を詳しくみてみましょう。
^
:行の先頭[a-zA-Z0-9._%+-]+
:1文字以上の英数字、ドット、アンダースコア、パーセント、プラス、ハイフン@
:必ず “@” が1つ含まれる[a-zA-Z0-9.-]+
:1文字以上の英数字、ドット、ハイフン\.
:ドット(エスケープシーケンス)
ドットはそのまま使用すると任意の1文字になってしまうため、ドット(.)という本来の意味で使うために\(バックスラッシュ)で任意の1文字という効果を消してあげます[a-zA-Z]{2,}
:2文字以上のアルファベット$
:行の末尾
いきなり複雑になりましたが、今までの知識を使えば理解できるはずです。メールアドレスがどのような形式だったかを考えながら見てみるとわかりやすいです。
電話番号の形式確認
日本の電話番号(例えば、090-1234-5678)の形式を確認する正規表現です。
^0\d{1,3}-\d{1,4}-\d{4}$
この正規表現を詳しくみてみましょう。
^
:行の先頭0
:最初に “0” が来る\d{1,3}
:1から3桁の数字-
:ハイフン\d{1,4}
:1から4桁の数字-
:ハイフン\d{4}
:4桁の数字$
:行の末尾
電話番号は0から始まるため、先頭が0かどうか判定するために^0
とする必要があります。
ここで初めてみる表現が出てきました。\d
は0〜9の数字を表す表現です。\d{ }
の{ }
内に数字を入れることで桁数を指定することができます。
URLの形式確認
URLの形式を確認する正規表現です。
^(https?|ftp)://[^\s/$.?#].[^\s]*$
^
:行の先頭(https?|ftp)
: “http” または “https” または “ftp”://
: “://” が続く[^\s/$.?#]
:スペース、スラッシュ、ドット、ドル、クエスチョンマーク、ハッシュ以外の文字.
:任意の文字[^\s]*
:スペース以外の任意の文字の0回以上の繰り返し$
:行の末尾
先頭がhttpsまたはftpで始まることを確認しています。いわゆるプロトコル部分です。
[^(文字)(文字)…]
は^の後ろに指定した文字以外です。一見複雑そうですが内容は簡単です。
\s
は初めて出てきました。\s
は空白1文字を表す正規表現です。その他にも\○
形式の表現はいくつかあるため、「定義済み正規表現」と検索してみるとよいです。ちなみに先ほど出てきた\d
も\s
と同じ定義済み正規表現です。
練習問題
ここまで読んで正規表現の使い方がある程度理解できたはずです。
理解を深めるために、いくつかの練習問題を解いてみましょう。ちなみに以下の問題はChat-GPT4oに考えてもらいました。
問題1:郵便番号の検証
日本の郵便番号は「123-4567」の形式です。これにマッチする正規表現を考えてみましょう。
ヒント:\dや繰り返し表現を使ってみましょう。
問題2:特定の単語の検索
テキストの中から「apple」「banana」「cherry」という単語を含む行を検索する正規表現を考えてみましょう。あらかじめ、テキストファイルを作成しておくとよいです。
問題3:日付の形式確認
「2023/06/23」の形式の日付にマッチする正規表現を考えてみましょう。
ヒント:問題1郵便番号と似ています。数字であることと桁数に注目しましょう。
おわりに
正規表現は最初は難しく感じるかもしれませんが、使いこなせるようになると非常に便利なツールです。
今回紹介した基本的な要素を理解し、実際に手を動かして練習することで、徐々に使いこなせるようになります。正規表現を使って、より効率的にデータを処理しましょう!
最後まで読んでいただき、ありがとうございました!質問やコメントがあれば、ぜひお寄せください。
コメント