正規表現について、サンプル中心にまとめてみた

0.はじめに

急ぎの方は、2章からお読み下さい。
駆け出しの頃、先輩に教えて頂いたことを、なるべく自分の言葉にしてまとめた記事を、Qiitaから移管しました。

駆け出しの頃の文章なので、今以上に拙い文章かと思いますが、参考にして頂けると嬉しいです!

1.正規表現とは(概要)

  • 正規表現は、ある文字の並び(文字列)を表現する一つの方式のこと。
  • 「文字の並び」のことを「パターン」と呼ぶこともある。
  • 「何でもいい何か1文字」等を表現できる。
    • たとえば「第X章」のことは、「第.章」と表現される。
      • 真ん中にある半角ピリオドは、正規表現において特別の意味を持たされた文字で、メタキャラクタと呼ばれる。
        • 「何か1文字」つまり「何でもいいけど、とにかく1文字」を表現するということができる。
        • この半角の「.」(ピリオド)は、「何でもいい1文字」とマッチするという言い方もする。

2.正規表現の特殊文字(メタキャラクタ)

以下に[メタキャラクタ](- 真ん中にある半角ピリオドは、正規表現において特別の意味を持たされた文字で、メタキャラクタと呼ばれる。)を一つずつ挙げおります。ここに上げたメタキャラクタ以外の文字については、正規表現において特別な意味はないそうです。単に普通の文字として扱って大丈夫とのことです。

2.1 ^ (べき乗)

半角の「^」(べき乗)は、行頭を示します。

^abc

この4文字は、行頭が「abc」で始まるパターンを表現します。行の途中に「abc」という3文字があっても、それとはマッチしません。

abcdefg
cba

2.2 $ (ドルマーク)

この半角の「$」は、 「^」に似ていて、行の終わりを示します。

です。$

この場合、

明日は晴れです。
明日は晴れですね。
明日は晴れです。はい。

この4文字は、行末にある「です。」という3文字とマッチしますが、行の途中にある「です。」や「ですね。」といった文字列とはマッチしません。

2.3 . (ピリオド)

半角の「.」(ピリオド)は、任意の1文字にマッチします。
※ただし、改行コードとはマッチしません。改行コード以外の1文字を示します。

2.4 [ ] (大括弧と大括弧閉じによる囲み)

「[」と「]」の二つで囲まれたものを「クラス」とか「文字セット」といいます。
囲みの中に書かれた任意の 1 文字にマッチします。

[abc]

この5文字は、 a, b, c の3文字のいずれか1文字を表現します。
3文字のうちどれでも良いので、とにかく1文字とマッチします。

a
b
c
d
e
f

こんな感じです。
次に、

[012345]

という8文字は、 0~5 の 6 個の数字のうちの1文字とマッチします。

0
2
5
6
8
9

さらに、二つのクラス(文字セット)をくっつけることもできます。

[abc][0123456789]

この 17 文字は

a3
c9
b5
d2
5a

となります。

省略した書き方

省略して書く方法もあります。

[0123456789]

という 12 文字は

[0-9]

という5文字で表現することができます。この場合の半角の「-」(マイナス)は、範囲を表わす特別な文字です。

[abcdefghijklmnopqrstuvwxyz]

というアルファベット全てを羅列した26文字は

[A-Z]

という5文字で表現することができます。
さらに、この省略した書き方も、以下のようにくっつけて書くことができます。

[A・・・Za・・・z_]

この、大文字小文字の全アルファベット24文字に「_」を加えた、合計49文字(24+24+1)は、

[A-Za-z_]

という 8 文字で表現することができます。
これは、半角のアルファベット(大文字でも小文字でもかまわない。)と半角の「_」のうち、いずれか1文字とマッチします。

また、

[亜-腕]

この5文字は、第1水準漢字1文字を表現します。このように文字を(アスキーコード・JIS コードの順序に配慮しながら)範囲指定で表現することができます。

2.5 ^……

これは、クラスの否定です。指定された文字集合以外の1文字を表現します。例えば

[^0-9]

という6文字は、「半角数字以外の任意の1文字」を表現します。
アルファベットとか漢字等々半角の数字以外なら何でもいい訳です。
もちろん

[^abcd]

とか

[^A-Za-z_]

などといった記述も可能です。

2.6 | (縦線)

これは、「または」という接続詞に該当するものです。たとえば

abc|main

という8文字は、

abc
main
def
sub

となります。

べき乗は、行頭を意味する言葉でもあります。たとえば、

^abc|^main

という 10 文字は、

abcマート
mainevent
ワイドabcde〜す
nain

と行頭にabcまたはmainが来ればマッチします。
加えて、いずれか一方とマッチすれば良い訳です。
これも、くっつけて書くことができるため、

^abc|main$|list.

などのように三つ以上のパターンをつなげても大丈夫です。

2.7 * (アスタリスク、または米印)

半角の「*」は、直前の1文字の0回以上の繰り返しを表現します。

a*

この2文字は、

a
aa
aaa
aaaa
(aという文字がない状態)

ということです。また、他の例としては、

abc*

という4文字は、

ab
abc
abcc
abccc
abcccc

となります。

※注意

「a* 」のような場合は、「文字が何もない状態」をも示します。つまり、「何とでもマッチする」ということになってしまいます。非常に不安定な検索文字列なので、こうした検索文字列は指定しない方が良いと言われています。

2.8 + (プラス)

半角の「+」は、直前の1文字の1回以上の繰り返しを表現します。
半角の「*」が0回以上の繰り返しだったのに対し、こちらは1回以上の繰り返しです。

abc+

この4文字は、

abc 
abcc
abccc
a
ab

となります。

ちなみに

.+


この2文字は、

(あらゆる文字列)


となります。
この正規表現は、任意の1文字の1回以上の繰り返しという意味のため、文字が何もない状態(つまり空白行)以外なら何とでもマッチするということになります。
最初に示した例の「第.章」というのは、第1章とか第2章等とはマッチしますが、数字部分が2桁以上になる「第 11 章」のような場合にはマッチしません。それに対して、

第.+章


とすれば第「123」章みたいなものにもマッチするということになります。
「.+」の2文字は、あまりに多くのものとマッチし過ぎるというデメリットはありますが、利用の仕方によってとても便利です。

また、もし「第」と「章」の間にくるものを厳密に数字だけに限定するのなら、

第[0-9]+章


とすると良いです。こうすれば、半角・全角の数字が間に挟まれる場合以外はマッチしないことになります。

2.9 ? (疑問符)

半角の「?」は、直前の文字の0回または1回だけの登場を表現します。たとえば

abc?


という4文字は、

ab
abc


のいずれかにしかマッチしません。

2.10 (……) (括弧と括弧閉じによる囲み)

半角の「(」と「)」で囲んだ部分は、一つのまとまり、グループとみなします。
もちろん、正規表現をこれで囲んでもかまいません。たとえば

(abc)+

という6文字は、

abc
abcabc
abcabcabc 


となります。

2.11 \ または ¥ (バックスラッシュまたは円マーク)

半角の「\」は、メタキャラクタの特別の意味を打ち消すためのものです。
たとえば「^」という文字を表現したい時には

\^

と2文字で書き表わさなければなりません。
半角の「.」は、

\.

となります。
半角の「\」を表現したい時は、

\\

と、2文字を書いて下さい。


以上が、正規表現のメタキャラクタと呼ばれるものの紹介です。
これを縦横無尽に使えるようになると、文字列の検索がきめ細かく行えるようになります。

とは言っても、
普通それほど複雑な正規表現検索を使うことは あまりないそうですが。笑

任意の1文字を示す「.」、1回以上の繰り返しを示す「+」
といったところを使えれば、それだけで単なる文字列検索よりもかなり便利になりそうです。

3 補足

正規表現は、UNIX 系コマンドで多く採用されています。たとえば、
grep, sed, awk, perl, emacs …… といったコマンドで採用されています。
(Windows 上で動作するソフトでも WZ エディタなどでは正規表現が使えます。)

そして、実はコマンドによって正規表現の記述方法が少しだけ異なります。
ですが、上に掲げた正規表現のルールは、ベーシックと言って良いそうです。

インターネットサーバによく組み込まれている perl では、次のような記述も行えます。
便利なので上げておきます。

\s => 空白文字1文字
\w => 英数字または「_」のうち1文字
\d => 数字1文字

3.1最長一致の原則

ある正規表現が同じ文字列の異なる長さの部分にマッチする場合、最も長い部分、最も包括的な部分にマッチするという原則です。
たとえば、「第1章と第2章」という7文字からなる文字列があった場合、

「第.+章」

という正規表現だと、「第1章」とマッチするとも考えられるし、「第2章」とマッチするとも考えられるし、はたまた文字列全体の「第1章と第2章」にもマッチすると言えます。
でも、こういう場合は「最長一致」ということで文字列全体とマッチするというのが正解です。注意です。

最後に

私自身うまく理解できておりませんので、間違い等あれば教えていただけると幸いです。
最後までありがとうございました。

PON

PON

30代で、完全未経験から独学でWeb系エンジニアになった人。 前職では、超絶ブラック企業にはまり込んでしまい、年間1200時間の残業をしていたが、娘が生まれたことで我に返って転職を決意。 現在は、大阪にあるベンチャー企業の自社開発プロジェクトで、リードエンジニアとして奮闘中。 主戦場はバックエンドで、Pythonでのデータ分析が武器。 とは言いつつ、SPAのフロントエンドを実装したり、インフラ設計したり、スクラム開発でプロジェクト運営したりするなんでも屋。 いつも、ググってきては誰かが書いてくれた記事を見て開発していたが、もらってばかりでなく世の中に返すこともしたいと思い、技術ブログをはじめる。 妻と1歳になる娘の3人暮らし。 最近は一日一食。 何かご用件がある方は、TwitterのDMからどうぞ。