#はじめに
学習中の備忘録です。
#概要
使用頻度の高いパターンについてまとめ
- 正規表現を実現する2つのメソッド
- 文字列の一部分を置換する
- 文字列が制約を満たしているか調べる
- 文字列の一部分を抽出する
- 正規表現のパターン表記一覧
#前提
Ruby 2.5.1
ターミナルにてirbコマンドで処理結果を確認
#正規表現を実現する2つのメソッド
###subメソッド
subメソッドは、文字列の指定した部分を別の文字列に置き換えるためのメソッドです。第一引数に置き換えたい文字列を指定し、第2引数に変換後の文字列を指定します。
また、操作したい文字列は/で囲みます。
irb(main):001:0> str = "りんごを食べる"
=> "りんごを食べる"
irb(main):002:0> str.sub(/りんご/,"みかん")
=> "みかんを食べる"
###matchメソッド
matchメソッドは引数に指定した文字列がレシーバの文字列に含まれているか否かをチェックするためのメソッドです。含まれている場合は、指定した文字列がMatchDataオブジェクトの返り値で得られます。また、含まれていない場合は、返り値としてnilが得られます。
※MatchDataオブジェクト
マッチした文字列等はMatchDataオブジェクトで返されます。MatchDataオブジェクトから文字列等を取り出す際は、以下の様に配列からデータを取り出す時と同様の形で取り出すことができます。
irb(main):001:0> str = "Hello, World"
=> "Hello, World"
irb(main):002:0> md = str.match(/Hello/)
=> #<MatchData "Hello">
irb(main):003:0> md[0]
=> "Hello"
#文字列の一部分を置換する
###電話番号からハイフンを取り除く
特定の文字を取り除く場合は、「特定の文字を空文字に置換する」と考えます。置換するメソッドはsubメソッドでした。以下のコードがハイフンを取り除くための処理です。しかしながら、subメソッドでは最初のハイフンしか置換されません。そこでgsubメソッドを用いることにします。
irb(main):001:0> tel = '090-1234-5678'
=> "090-1234-5678"
irb(main):002:0> tel.sub(/-/,'')
=> "0901234-5678"
# 最初のハイフンしか置換されない
irb(main):003:0> tel.gsub(/-/,'')
=> "09012345678"
※グローバルマッチのg
subの前にgが追加された、gsubメソッドが登場しました。このgが意味するのは、グローバルマッチと呼ばれ、文字列内で指定した文字が複数含まれている場合、その全てを置換するという意味になります。gsubではなくsubを使用した場合、初めの1つだけ置換されます。
#文字列が制約を満たしているか調べる
###パスワードに英数字8文字以上という制約を設定する
今回はパスワードに「Hoge1234」という大文字小文字を区別した英字と数字を使用することを想定します。
matchメソッドを使用して以下のように記述します。
irb(main):001:0> pass = 'Hoge1234'
=> "Hoge1234"
irb(main):002:0> pass.match(/[a-z\d]{8,}/i)
=> #<MatchData "Hoge1234">
- [a-z]: 角括弧で囲まれた文字のいずれか 1 個にマッチ
- \d: 数字にマッチ
- {n, m}: 直前の文字が少なくとも n 回、多くても m 回出現するものにマッチ
- i: 大文字・小文字を区別しない検索
####[a-z] : 角括弧で囲まれた文字のいずれか 1 個にマッチ
](角括弧)を使用することで角括弧で囲まれた文字のいずれか1つがマッチするかをチェックしています。また、-(ハイフン)を使用することで範囲を設定することができます。[a-z]はアルファベットのa からzまでのいずれかにマッチという意味になります。
(例)a~cの英字を抽出
irb(main):001:0> 'dog'.match(/[a-c]/)
=> nil
「dog」という単語にはa ~ cのどの英字も含まれていないのでマッチしません。
####\d : 数字にマッチ
このdは数字を表します。数字を表すdのような文字を特殊文字と呼びます。特殊文字を使用する場合は直前に\を記述するというルールが存在します。
今回は、\dは角括弧の内部にあるので、[a-z\d]は「英数字のいずれか1つにマッチ」という意味になります。
(例)数字のみ抽出する
irb(main):001:0> 'I have 3 pens'.match(/\d/)
=> #<MatchData "3">
####{n, m} : 直前の文字が少なくとも n 回、多くても m 回出現するものにマッチ
波括弧を使用することで文字数の制約を追加することができます。{8, }は、直前の文字が少なくとも8回出現するものにマッチという意味になります。今回、波括弧の直前は[a-z\d]でした。つまり、英数字のいずれか1つが少なくとも8回出現するものにマッチという意味になります。
(例)少なくとも4回、多くても6回出現するものにマッチ
irb(main):001:0> '12345678'.match(/\d{4,6}/)
=> #<MatchData "123456">
irb(main):002:0> '123'.match(/\d{4,6}/)
=> nil
####i : 大文字・小文字を区別しない検索
最後にiオプションを加えることで大文字・小文字を区別せずに検索します。iオプションを付けない場合ですと、[a-z]と小文字で記述しているので大文字にマッチしなくなってしまいます。
(例)大文字・小文字の区別
irb(main):003:0> 'Cat'.match(/cat/)
=> nil
irb(main):004:0> 'Cat'.match(/cat/i)
=> #<MatchData "Cat">
####実践的な使用方法
パターンにマッチした場合はマッチした要素の配列が返されます。またマッチしなかった場合はnullが返ってくるので、その性質を使用してif文で処理を分けます。
pass = 'Hoge1234'
if pass.match(/[a-z\d]{8,}/i)
//パスワード設定の処理
else
puts 'パスワードの形式が間違っています。'
end
#文字列の一部分を抽出する
###メールアドレスからドメインの部分のみ抽出する
今回は、「hoge@abcd.com」というアドレスから「@abcd.com」の部分のみを取得したいと思います。
今回もmatchメソッドを使用することで抽出することができます。
rb(main):001:0> mail = 'hoge@abcd.com'
=> "hoge@abcd.com"
irb(main):002:0> mail.match(/@.+/)
=> #<MatchData "@abcd.com">
- . : どの1 文字にもマッチ
- + : 直前の文字の 1 回以上の繰り返しにマッチ
####. どの1文字にもマッチ
ハイフンやピリオドなど含めた全ての英数字において、どの1文字にもマッチします。
irb(main):001:0> 'hoge'.match(/./)
=> #<MatchData "h">
####+ 直前の文字の 1 回以上の繰り返しにマッチ
直前の文字が1回以上の繰り返しにマッチします。
irb(main):001:0> 'aaabb'.match(/a+/)
=> #<MatchData "aaa">
これらを踏まえますと、.+は何かしらの文字が1回以上繰り返すものにマッチします。先頭に@を付けることで「@から始まり、何かしらの文字が1回以上繰り返すものにマッチ」という意味になります。
こうすることでメールアドレスからドメイン部分のみを抽出することができます。
#正規表現のパターン表記一覧
パターン | 意味 |
---|---|
[a-z] | 角括弧で囲まれた文字のいずれか 1 個にマッチ |
\d | 数字にマッチ |
{n, m} | 直前の文字が少なくとも n 回、多くても m 回出現するものにマッチ |
. | どの1 文字にもマッチ |
+ | 直前の文字の 1 回以上の繰り返しにマッチ |
#まとめ
正規表現について新たな学習があれば適宜追記するかもです。