大文字小文字数字記号を最低1文字以上含む正規表現
^(?=.*[!-/:-@[-`{-~])(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[!-~]{10,}$
正しいかチェックしてみる
確認のため上記文字列をテキストエディタで検索してみる(もちろん正規表現を有効にして)
例えばemeditorだとマッチした箇所は緑色にハイライトされる。
こうすると簡単に色々なパターンのマッチ/アンマッチをチェックできる。
以下を見れば意図したとおり大文字小文字数字記号を最低1文字以上にマッチしていることがわかる。
残念な例
ネットでググると1文字以上のマッチを肯定先読みでチェックしている記事はよく見るが、折角文字種をチェックしているのに肝心のマッチ部分をドット(.)にしてる残念なパターンを目にする
^(?=.*[!-/:-@[-`{-~])(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z]).{10,}$
これだと確かに指定した文字種は最低1文字含まれるが、指定していない文字まで含めることができてしまう。
つまり以下の文字にもマッチしてしまう
正規表現で記号を表現する簡単な方法
ASCII文字に含まれる(スペース以外の)印字可能な記号を以下の正規表現で表している。
これについて少し細くする。
[!-/:-@[-`{-~]
正規表現は文字クラスを []
で定義できる。
例えば [a-z]
は abcdefghijklmnopqrstuvwxyzのいづれか1文字
と全く同じ意味だ。
この文字クラスはより正確に言うと aという文字の文字コード(97)
から zという文字の文字コード(122)
の間に含まれる文字コードにマッチする、という意味である。
asciiコードではアルファベットはa(97)からabc順に昇順に並んでいるので、[a-z]
がa~zのいづれか1文字を表すのである。
これが理解できていれば [z-a]
という文字クラスは間違いであることが一瞬でわかるだろう。
話を記号に戻そう。
上記のASCIIコード表を見ると、31までが制御文字で32(スペース)から印字可能な文字(いわゆるキーボードで入力する文字)が始まって126(~)まで続いている。だから、英数記号を表す文字クラスは非常にシンプルに [!-~]
と記述できる。ではこの中から記号のみを表現するにはどうすればよいか。あいにく 文字クラスにはexcludeを指定する方法は用意されてない(正規表現ライブラリに依っては除外設定も可能とのことです、コメント参照) ので、文字コードが連続していない場合は分けて記述するしかない。つまりこうだ。
!-/
:-@
[-`
{-~
これらを一纏めにすれば冒頭の正規表現で使った文字クラスができあがる。
[!-/:-@[-`{-~]