20201010_アウトプット(正規表現)

アプトプット画像

学んだこと

正規表現Ruby編)

  • 正規表現を用いることで、文字列の置換・抽出・制約調査ができる

Rubyにおいて、正規表現を利用するために重要な2つのメソッド(文字列)

メソッド名 役割
sub 置換
match 含まれているか確認(抽出・制約調査)
subメソッドについて
  • 第一引数に「置き換えたい文字列」を指定して、第二引数に「変換後の文字列」を指定する。
irb(main):001:0> str = "りんごを食べる"
=> "りんごを食べる"

irb(main):002:0> str.sub(/りんご/,"みかん")
=> "みかんを食べる"


matchメソッドについて
  • 指定した文字列が含まれている場合には、戻り値として「MatshData」というオブジェクトが表示される。

  • 含まれていない場合には、戻り値として「nil」が返される。

irb(main):001:0> str = "Hello, World"
=> "Hello, World"

irb(main):002:0> str.match(/Hello/)
=> #<MatchData "Hello">

irb(main):003:0> str.match(/Good/)
=> nil
  • 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"
Rubyのプログラムにsubやmatchなどを適用させるには▶︎if文を用いる
str = gets.chomp
if str.match(/good morning/)
  puts 'おはようございます!'
else
  puts 'あいさつが異なるようです。'
end

subメソッド(置換)を利用して、電話番号からハイフンを取り除こう

  • 「gsubメソッド」を使う。
メソッド 違い
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"


matchメソッド(含まれるか)を利用して、パスワードに英数字8文字以上という制約を設定しよう

【英数字が8文字以上の時】
irb(main):001:0> pass = 'Hoge1234'
=> "Hoge1234"

irb(main):002:0> pass.match(/[a-z\d]{8,}/i)
=> #<MatchData "Hoge1234">
【英数字が8文字未満の時】
irb(main):001:0> pass = 'Hoge123'
=> "Hoge123"

irb(main):002:0> pass.match(/[a-z\d]{8,}/i)
=> nil

「matchメソッド」にプラスして、どの様にマッチしているか確認することができる。

パターン 役割
[a-z] 角括弧で囲まれた文字列いずれか1つがマッチするか
\d 数字がマッチするか
{n, m} 最低でn回、最高でm回出現するか(文字数制限)
i iを入れることで大文字・小文字を区別せずに検索
(付けないと全て小文字のみとなる)

補足:バックスラッシュは「オプションキー + ¥」(mac)


matchメソッド(含まれるか)を利用して、メールアドレスからドメイン部分のみ抽出しよう

irb(main):001:0> mail = 'hoge@gmail.com'
=> "hoge@gmail.com"

irb(main):002:0> mail.match(/@.+/)
=> #<MatchData "@gmail.com">

下記、2つのオプションを組み合わせて、「@から始まり、何かしらの文字が一回以上繰り返すものにマッチ」と抽出をかけられる。

パターン 役割
.(ピリオド) 全ての英数字においてどの1文字にもマッチ
+ ”+”の直前の文字が1回以上の繰り返しにマッチ

組み合わせることにより、もしも「@~」という文字列でない場合には、メールアドレスとして認めないという処理に応用できる。




正規表現Ruby on Rails編)▶︎バリデーションへの応用

郵便番号

  • 「3桁の数字」+「ハイフン」「4桁の数字」の構成である郵便番号が正しく入力しているか判別する。
irb(main):001:0> postal_code = "150-0044"

irb(main):002:0> postal_code.match(/\A\d{3}[-]\d{4}\z/)
=> #<MatchData "150-0044">
パターン 役割
\A \Aの直後においた文字が、「文字列の先頭」にある場合にマッチ
\z \zの直前においた文字が、「文字列の末尾」にある場合にマッチ
{数字} {}に囲まれた数字の回数があるとマッチ
Railsのモデルにこのように記入して使える!
validates :postal_code, format: { with: /\A\d{3}[-]\d{4}\z/, message: 'を入力してください' }



全角かな/カナの区別

irb(main):001:0> full_name = "山田はな子"

irb(main):002:0> full_name.match(/\A[ぁ-んァ-ン一-龥]+\z/)
=> #<MatchData "山田はな子">

irb(main):003:0> full_name = "yamadaハナ子"

irb(main):004:0> full_name.match(/\A[ぁ-んァ-ン一-龥]+\z/)
=> nil

文字列の先頭から末尾まで、「かな」あるいは「カナ」あるいは「漢字」であるか確認をしてしている。

パターン 役割
[ぁ-んァ-ン一-龥] かな/カナ/漢字であるかチェックする
Railsのモデルにこのように記入して使える!
with_options presence: true, format: { with: /\A[ぁ-んァ-ン一-龥]+\z/, message: '全角文字を使用してください' } do
  validates :first_name
  validates :last_name
  validates :first_name_kana
  validates :last_name_kana
end



passwordの英数混合の判断

passwordで活用するために、

  • 英数字が混合しているか

  • 少なくとも1回以上続き、末尾までそれが続くか

の2つの条件を作る。

irb(main):001:0> password = "T2o0k2y0o"

irb(main):002:0> password.match(/\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i)
=> #<MatchData “T2o0k2y0o”>
パターン 役割
?= "?="の後に書いた文字列とマッチしているか
.*? ".*?"のあとに続く種類の内容の文字がいくつかあるかもしれないし、ないかもしれない
Railsのモデルにこのように記入して使える!
PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
validates_format_of :password, with: PASSWORD_REGEX, message: 'には英字と数字の両方を含めて設定してください' 

上記の正規表現の意味は、ざっくりいうと”「英字(大文字・小文字どちらでもOK)」と「数字」がぞれぞれ1文字以上ずつあるパスワードか?”という意味になる。

反対を言えば、

  • 「空白のみ」

  • 「"_"や"."などの英数字以外」

  • 「1だけ(英字がない)」

  • 「aだけ(数字がない)」

のような場合には「nil」になってしまう、ということ。



積み残し(復習したいところ)

  • devise rollback方法

  • カラム追加の方法

  • Rails勉強会



感想

正規表現についてぱっと見難しそうに見えたが、読み解いてみると、分かりやすくて面白かった。
学んでいて感じたことは、deviseでデフォルトで作成されるもの(emailやpassword)のバリデーションをアレンジしたいときはどうやってやるんだろうと感じた。(裏側で自動生成してくれて楽な分、普段使うアプリケーションはもっと色んな認証があるため)

バリデーションだけでなく、実際に入力したメアドに確認メールが送信され、そこからURL先に飛んだら、会員登録完了といった認証があるがそれはどうやってやるんだろうと思った。
調べてみると「PHP」の技術が必要そうだったので、カリキュラムを先に進めながら学んでいきたい。