正規表現について学習ノート(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漢字を区別したり、パスワードの英数字混合や郵便番号をチェックできたりする
この記事が気に入ったらサポートをしてみませんか?