正規表現について学習ノート(2)

Ruby on Railsにおけるバリデーションへの応用

  • 郵便番号

  • 全角かな/カナ漢字の区別

  • passwordの英数混合の判断


郵便番号

郵便番号は先頭に3桁の数字、そしてハイフン、末尾に4桁の数字

irb(main):001:0> postal_code = "123-4567"

irb(main):002:0> postal_code.match(/\A\d{3}[-]\d{4}\z/)
=> #<MatchData "123-4567">

{n}

直前の文字が n 回出現する場合にマッチ。
例) a{3}は、「『a』という文字が3回出現するものにマッチする」
今回はハイフンを挟んでd{3}とd{4}なので、ハイフン前は「数字が3回出現するものにマッチする」、ハイフン後は「数字が4回出現するものにマッチする」という意味。

\A

\Aの直後に置いた文字を、文字列の先頭に持つ場合にマッチ。
今回は\A\d{3}としているので、文字列の先頭に3桁の数字があるとマッチする。

\z

\zの直前に置いた文字を、文字列の末尾に持つ場合にマッチ。
今回は\d{4}\zとしているので、文字列の末尾に4桁の数字があるとマッチする。

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 = "佐藤ローラ"

irb(main):004:0> full_name.match(/\A[ぁ-んァ-ヶ一-龥々ー]+\z/)
=> #<MatchData "佐藤ローラ">

irb(main):005:0> full_name = "suzukiユウ香"

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

[ぁ-んァ-ヶ一-龥々ー]

[ぁ-んァ-ン一-龥]
「ぁ」から「ん」まで、「ァ」から「ン」まで、「一」から「龥」までの文字でチェックを行う。これらの文字の範囲は、Unicodeにおける範囲。
「ァ-ヶ」
utf-8文字コード上で「ヴ」「ヵ」「ヶ」はカタカナ「ン」の後に配列されているため「ァ-ヶ」と記載が必要。
→「々」
「々」はutf-8文字コード上で記号として認識されているため、別途「々」の指定を追加する必要がある。[ぁ-んァ-ヶ一-龥々]と表現することで、あらゆる日本語に対応する言葉ができる。
→「ー」
長音を区別する場合は、[ぁ-んァ-ヶ一-龥々]の末尾に「ー」を追記する。
したがって、[ぁ-んァ-ヶ一-龥々ー]という記載になる。

今回は名前全体がかな/カナ/漢字であるかをチェックしたいので、先に出てきた\Aと\zと+を同時に用いて、先頭から末尾までかな/カナ/漢字である場合にのみマッチさせる。3つ目のチェックには先頭にsuzukiとアルファベットを使用してるためマッチしておらずnilが返ってきている。

Railsのモデルにバリデーションを設ける記載例

with_options presence: true, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/, message: '全角文字を使用してください' } do
  validates :first_name
  validates :last_name
end

passwordの英数混合の判断

  • 英数字は[a-z\d]でチェックできる。

  • 英字もしくは数字が少なくとも0回以上続き、末尾までそれが続くことが前提条件。

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

irb(main):002:0> password.match(/\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i)
=> #<MatchData “B2o0t2y0s”>

?=

?=の直後に設定した文字でチェックをかけて、設定した文字が続く文字列が存在する場合、その文字列にマッチする。

例)
irb(main):001:0> name = "ゴールデンカムイ"

irb(main):002:0> name.match(/ゴールデン(?=カムイ)/)
=> #<MatchData "ゴールデン">

irb(main):003:0> name = "ゴールデンボンバー"

irb(main):004:0> name.match(/ゴールデン(?=カムイ)/)
=> nil

*?

「*」は、直前の1文字が0回以上続くとマッチする。例えば、「camp*」とした場合、「cam」「camp」「campp」「camppp」などがマッチする。
この「*」の後に?をつけることで、チェックした文字列の中で、?の直後の文字が出てきた段階でその1文字のみ返す。

/\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i の解説

 .*?[a-z] 

「改行以外の文字が0回以上続いたあとの英字1文字にマッチ」

.*?[\d]

「改行以外の文字が0回以上続いたあとの数字1文字にマッチ」

\A(?=.*?[a-z])(?=.*?[\d])

「改行以外の任意の文字0回以上とaからzの1文字の先頭位置、かつ、改行以外の任意の文字0回以上と数字1文字の先頭位置にマッチするもの」

/\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i

「先頭が任意の文字0回以上と英数字ではじまっていて(ここまでが②)、末尾が英数字の1回以上の連続する文字列にマッチし、大文字小文字の区別がない」

Railsのモデルにバリデーションを設ける記載例

PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
validates_format_of :password, with: PASSWORD_REGEX, message: 'には英字と数字の両方を含めて設定してください' 

.freezeは、PASSWORD_REGEXという変数が編集されないようにするメソッド(正規表現とは関係なし)


正規表現のパターン表記まとめ

正規表現のパターン表記まとめ

まとめ

  • 細かいバリデーションを設定するために、正規表現は有用である

  • 複雑な表現方法を用いることで、全角かな/かなor漢字を区別したり、パスワードの英数字混合や郵便番号をチェックできたりする


この記事が気に入ったらサポートをしてみませんか?