Kintarou'sBlog

プログラミング学習中。学習内容のアウトプットや読書で学んだことなど随時投稿!

【Ruby】正規表現

こんにちは😊Kintarouです。

現在エンジニア転職を目指してTECH CAMPにてプログラミング学習中です👨‍🎓
夢はフリーランスエンジニアになって働く人が働きやすいシステムを作ること!
と、愛する妻と海外移住すること🗽

プログラミングや読んでいる本のことなど、ブログに書いていきます!
twitter : https://twitter.com/ryosuke_angry


今日は正規表現についてまとめます。

参考にさせて頂いた記事 qiita.com Ruby正規表現を確認できるエディタ rubular.com

正規表現とは

正規表現とは何かを一言で言い表すのは難しいようです。私としては、「文字列をパターンとして包括的に表現する方法」というイメージで解釈しています。

書き方

まずは簡単な一例です。

/\A\d{3}-\d{4}\z/

上記は555-5555など、文頭に半角数字3文字、-(ハイフン)、文末に半角数字4文字(=郵便番号のパターン)を表現しています。
このように表現することで、123-4567でも987-6543でも同じパターンであれば抜き出したり検索することが出来、制限をかけることも可能になります。

同じ意味で、表現方法がバラバラな場合でもパターンに包括出来れば表現できます。

/アイ[フホ][]?[]?/ #とすると  
#先日『アイフォン』を買った。  
#私の友達は皆『アイフォーン』を持っている。  
#やっぱり『アイホン』が人気のようだ。  

#『』内の文字列は違うが、全て包括して表現出来ている。

基本のルール

まず基本のルールとして

/ (スラッシュで囲った中にパターンを書く) /

という感じに「 / 」で囲んで表現します。

[ ] 、\d

例えば表現したい文字列が半角の「 1 (1桁)」だと分かっていれば、表現としては

/1/

で大丈夫です。
では表現したい文字列が半角1桁ではあるが、0 〜 9のどの数字かわからない場合は

/[0-9]/  
#または  
/\d/

で表現します。

[ ]内は”どの文字がくるかわからないけどこの中のどれか1文字!”を表現できます。
[0-9]は0〜9の数字1文字を表現しています。「-」は範囲を表し、例えばa〜zの小文字アルファべットのどれか1文字を表現する場合は[a-z]と表現します。

 ※ちなみに全角数字の場合は[0-9]と、数字を全角にすれば表現できます。半角でも全角でも、とにかく数字1桁!とする場合は同じ[ ]内に[0-90-9]とすればよいです。

先のアイフォンの例では[フホ]という表記がありましたが、あれは"アイの次にくる文字は[フ]か[ホ]の2パターンしかないよ"ということです。

 ※[0-9]が[0]か[-]か[9]の内のどれか。という表現にならないのは、「-」が特殊文字だからです。
  もし上記の表現にしたい場合は[-09]や[09-]とすれば、[0]か[9]か[-]の内どれか。という表現になります。

\dはメタ文字と呼ばれ、[0-9]と同じ意味を持ちます。

{n,m} {n}

数字が何桁かにわたる場合

#2桁数字  
/\d\d/  
#5桁数字  
/\d\d\d\d\d/

とすれば良いですが少し冗長なので

#2桁数字  
/\d{2}/  
#5桁数字  
/\d{5}/  

#2〜5桁の数字  
/\d{2,5}/

と表現できます。

ここまでで、郵便番号を以下のように表現できます。

/\d{3}-\d{4}/
# \d(半角数字){3}(3桁)、-(ハイフン)、\d(半角数字){4}(4桁)

555-5555  
postal-code:333-3333

以上でも大丈夫ですが、上記のpostal-code:333-3333の方は文頭に別の文字列が入っているのでパターンに含めたくないという場合があります。
その他12345-67890などの文字列が並んでいたとすると”345-6789”の部分がパターンに含まれますが、それを良しとしない場合もあります。
その場合、文頭から文末まで/\d{3}-\d{4}/で表現されている文字列。とする必要があります。

\A \z ^ $

\Aを先頭に入れることで、後に続く文字列が"文頭に入っていた場合"に抽出できます。
\zを最後尾に入れることで、その前の文字列が"文末に入っていた場合"に抽出できます。

この2つを組み合わせることで、文頭に半角数字3文字、-(ハイフン)、文末に半角数字4文字を表現できます。

/\A\d{3}-\d{4}\z/

555-5555

注意すべきは、この文頭・文末というのは改行や空白も含まれるということです。
なのでこの表現はバリデーションなど、厳密な表現の際に使われるものと思われます。

行頭(^)、行末($)を表現する場合は以下を使います。

/^\d{3}-\d{4}$/

555-5555

?

最後にアイフォンの例であった「?」を解説します。
アイのあとに続く文字が[フ]か[ホ]の場合に[フホ]と書くよ。というのは先に述べましたが、次に続く[ォ]は『アイホン』の場合ありません。
このように、[ ]内の文字がある場合と"無い場合"も含めたい時は「?」をつけることで表現できます。
そのため先の例は正確に言うと
アイフォン、アイフォーン、アイホンの他、アイフン、アイフーン、アイホーン、アイホォン、アイホォーンも包括していることになります。

まとめ

最後の例のように、正規表現で理想のパターンのみを表現するのは難しいようです。
要件によって求められる精度は変わりますが、ある程度は正規表現によって制限し、あとはrubyのメソッド(grepなど)で不純物を除外するといった方法で精度を高めていくという方法も有りだそうです。

以上、どなたかの参考になれば幸いです😊