概述 續接上文的密碼校驗要求: ![xuqiu.jpg][1] 這個需求有兩個難點,一,是如何使用正則匹配所有半形英文標點符號,二,是如何驗證密碼段中在要求的四種(大寫字母,小寫字母,數字,標點符號)類型中至少存在三種。 第一個難點:如何使用正則匹配所有半形英文標點符號在上文中已經得以解決,所以在這 ...
概述
續接上文的密碼校驗要求:
這個需求有兩個難點,一,是如何使用正則匹配所有半形英文標點符號,二,是如何驗證密碼段中在要求的四種(大寫字母,小寫字母,數字,標點符號)類型中至少存在三種。
第一個難點:如何使用正則匹配所有半形英文標點符號在上文中已經得以解決,所以在這裡我們主攻第二個難點並完成完整的符合需求的表達式。
太長不看版
滿足需求:完全符合上述圖片的校驗需求,密碼段中在要求的四種(大寫字母,小寫字母,數字,標點符號)類型中至少存在三種
解決方案:靈活運用正則中的零寬度負先行斷言:
^(?!^[0-9a-z]+$)(?!^[0-9A-Z]+$)(?!^[0-9\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[a-zA-Z]+$)(?!^[a-z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)[a-z0-9A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$
能被匹配到的則滿足上述圖片需求
詳細解釋
零寬斷言是正則表達式中的一種進階使用方法,靈活運用零寬斷言能讓正則表達式變得更為簡練,並且使其功能變得更為強大。
正則的零寬斷言一般有以下四種:
借用司徒正美大大的解釋
但可惜的是javascript並不支持(?<=exp)和(?<!exp)的用法。而我們這次使用的則是零寬度負先行斷言
零寬度負先行斷言原理解釋:
(?!exp)這個斷言的用法是:只有當字元串右側不出現匹配exp的字元串時才匹配正則表達式。
我們先從一個簡單的例子講解:
如果我們要匹配一串字元,所有字元必須為小寫字母或者數字,並且必須要有小寫字母。
那麼換一種思路,就是我們的字元串必須為小寫字母或數字構成,並且不能為純數字。
所以我們使用零寬度負先行斷言,則可以寫成
^(?!^[0-9]+$)[a-z0-9]+$
斷言(?!^[0-9]+$)則表示純數字的組合不能被匹配。
把例子加深一下:
我們要匹配一串字元,所有字元必須為小寫字母或者數字,並且必須同時有小寫字母和數字的存在。
那麼換一種思路,就是我們的字元串必須為小寫字母或數字構成,並且不能為純數字或者是純小寫字母。
所以我們使用零寬度負先行斷言,則可以寫成
^(?!^[0-9]+$)(?!^[a-z]+$)[a-z0-9]+$
斷言(?!^[0-9]+$)則表示純數字的組合不能被匹配;斷言(?!^[a-z]+$)則表示純小寫字母的組合不能被匹配。
二者相組合,就能夠把所有純數字和純小寫字母的組合給排除掉了,剩下的就是同時有小寫字母和數字的組合。
怎麼樣,思路出來了嗎?
把例子再次深化:
我們要匹配一串字元,所有字元必須為小寫字母或者數字或者大寫字母,並且必須至少有三種字元中的兩種。
那麼我們整理下思路,實際上就是我們的字元串必須為上述三種字元構成,並且不能為純數字或純小寫字母或純大寫字母。
所以我們使用零寬度負先行斷言,則可以寫成
^(?!^[0-9]+$)(?!^[a-z]+$)(?!^[A-Z]+$)[a-z0-9A-Z]+$
這樣做,就可以把純數字(?!^[0-9]+$),純小寫字母(?!^[a-z]+$),純大寫字母(?!^[A-Z]+$)統統排除了。
練級完成,是時候面對大BOSS了
在上一篇JS的JS正則密碼複雜度校驗文章中,我們知道了要匹配所有的半形表單符號的正則表達式是:
/[\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]/
配合上面的斷言語句,我們可以去單挑boss了:
驗證密碼段中在要求的四種(大寫字母,小寫字母,數字,標點符號)類型中至少存在三種,我們就可以將思路轉換為:
在只有上述四種類型範圍的字元串中,找出所有從頭到尾只有兩種以下字元的字元串並將它們排除就可以了。
那麼根據排列組合,我們需要排出的就是
數字和小寫字母(?!^[0-9a-z]$),
數字和大寫字母(?!^[0-9A-Z]$),
數字和符號(?!^[0-9\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]$),
小寫字母和大寫字母(?!^[a-zA-Z]$),
小寫字母和符號(?!^[a-z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]$)
還有大寫字母和符號(?!^[A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]$)
於是乎,最後的正則成品:
^(?!^[0-9a-z]+$)(?!^[0-9A-Z]+$)(?!^[0-9\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[a-zA-Z]+$)(?!^[a-z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)(?!^[A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$)[a-z0-9A-Z\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$
就能滿足我們的需求
總結
正則表達式的學習入門比較容易,上手也不難。在面對一些很長的正則表達式或者看似奇葩的正則表達式匹配需求時,我們不妨靜下心來,慢慢地去分析它們,找到個中規律之後,正則表達式的迷霧也就被揭開了。而正則表達式這把神器,也能被我們隨心所欲地揮舞了。