天天看點

文盲的正規表達式入門,實戰篇(歡迎提問,持續更新)如何寫出正則?

目錄

如何寫出正則?

手機号碼正則

電子信箱位址正則 

符合一定規律的字元串比對

密碼複雜度驗證正則

提取html标簽外(正文中)的内容

之前寫的文章文盲的正規表達式入門,個人認為寫的還可以,但是網絡上充斥着的同質化内容太多了,結果整整幾年了,也沒幾個人看過,郁悶哦

再有就是,雖然老顧推薦給了幾個人看,但感覺小朋友們的正則水準提升的并不明顯,也許讀正則都費勁?

那麼,這次老顧就結合自己的正則入門來幾個實戰,來幫助新手入門正則吧。

如何寫出正則?

正則的規則,各定義的意義已經在正則入門篇裡講過了,這邊不再重複,那麼如何寫出正則呢?其實這就是把我們的思路改成正則的邏輯,就像漢語翻譯成英語,日語翻譯成漢語一樣。你的思路越清晰,那麼正則的規則就越詳細。

手機号碼正則

一個常見的例子:手機号驗證。

大咧咧的人,比如老顧,他的思路是這樣的:數字1開頭(開頭的意義表示前邊不能有其它數字哦),後邊跟10個數字,且10個數字後沒有跟随其它數字,那麼這個正則寫下來就是

^1    ,數字1開頭
\d{10},10個任意數字
$

組合起來就是 ^1\d{10}$
           

這個用來驗證單一的手機沒問題,但如果在文中提取,那麼就需要變形一下

(?<!\d)    前邊不能是數字
1          數字1開頭
\d{10}     10個任意數字
(?!\d)     後邊不能是數字

組合起來

(?<!\d)1\d{10}(?!\d)
           

這樣,這個正則就可以用來提取文本中的手機号碼了

注:這裡用到的左斷言,js是不支援左斷言的,需要自己注意哦

同樣是手機号碼,有的人就很細心,非得把号段也給囊括進來,不是指定的号段,就不是國内大陸的手機号碼。。。Hmmmm,行吧,反正這樣的人确實有不少

那麼,這樣的人,他會去百度一下,國内手機号段都有哪些

文盲的正規表達式入門,實戰篇(歡迎提問,持續更新)如何寫出正則?

然後,他們搞到了這麼一個表格,于是,他們就按照這個内容寫正則了,思路很清奇的哦

數字1開頭,這個不變,然後,第二位的數字隻有3456789,為了更嚴格,他們不會寫成[3456789],因為每個數字後可以跟随的第三位數字範圍不一樣,于是,他們把正則寫成了這樣

^1([38]\d|4[01456789]|5[012356789]|6[567]|7[35678]|9[189])\d{8}$

拆開就是

^1
(
    [38]\d
    |
    4[01456789]
    |
    5[012356789]
    |
    6[567]
    |
    7[35678]
    |
    9[189]
)
\d{8}
$

13和18的第三位數字不限,0-9都有,是以是 [38]\d
14裡面第三位沒有2和3
15裡面第三位沒有4
其他類似。。。
           

額。。。。如果有看不明白的,記得留言哦。

看看,手機号碼的驗證或比對,是不是很簡單,基本上思路擺出來,翻譯成正則符号即可,不明白各個符号的,可以回頭重新看正則入門哦

電子信箱位址正則 

那麼,再來一個常見的,比如電子信箱。

好的,電子信箱的格式,咱們來描述一下:

1、有且隻有一個@符号

2、隻能由字母數字下劃線點和減号構成其他部分

3、@符号之後,為域名部分,域名部分沒有下劃線支援,@符号前為使用者名部分,可以支援描述2的所有字元

4、域名長度不确定,可能由多個.,至少有1個.,域名結束部分為2-4個字元(中文域名就算了,不想支援)

那麼,這個正則按照上邊的邏輯來實作一下

[a-zA-Z0-9_\.-]+@([a-zA-Z0-9-]+\.)+[a-z0-9]{2,4}

首先,有且隻有一個@

然後,使用者名部分由字母數字下劃線點和減号構成,即:[a-zA-Z0-9_\.-]

在然後是域名部分,由字母數字點和減号構成,但是.要作為域名分隔符,是以他的字元集為字母數字及減号,即:[a-zA-Z0-9-]

域名構成格式為 字元.字元.字元,是以除去最後一個字元,前邊的片段就可以寫成 ([a-zA-Z0-9-]+\.)+

最後,得出信箱正則 [a-zA-Z0-9_\.-]+@([a-zA-Z0-9-]+\.)+[a-z0-9]{2,4}
           

符合一定規律的字元串比對

然後,老顧碰到一個同學問了個正則比對問題,有一個字元串:“名稱:量子力學教程,作者:周世勳,ISBN:9787040262780,出版社:高教名稱:量子力學教程(第二版)學習指導,作者:倪緻祥,ISBN:9787040303506,出版社:高教”,怎麼把他分成多本書的資訊,且要保留分組

首先,這個字元串并不規整,他這個字元串包含了兩本書的資訊,但第一本數的出版社資訊和第二本數的名稱描述連在一起了。。。但整體上看,這個字元串還是比較規整的

那麼,我們來描述一下:

1、以“名稱:”開頭的字元串,包含作者、ISBN、出版社資訊,且描述都用:,描述後的内容都不包括逗号,以逗号結束描述的對應資訊

那麼,第一個正則片段應該是

(名稱):([^,]*?),(作者):([^,]*?),(ISBN):([^,]*?),(出版社):([^,]*?)
           

應該沒有人看不懂這個吧

但是這個正則比對出來的結果,略微不那麼對頭,出版社資訊不見了?

文盲的正規表達式入門,實戰篇(歡迎提問,持續更新)如何寫出正則?

 如果最後一個括号内,不加非貪婪模式,那麼他又沒辦法将字元串分成兩條比對了

是以,這個正則加個右斷言修飾好了

出版社後的内容後邊要麼字元串結束,要麼是下一本書的開頭,即“名稱:”

是以正則修改一下

(名稱):([^,]*?),(作者):([^,]*?),(ISBN):([^,]*?),(出版社):([^,]*?)(?=(?:$|名稱:))
           

(?=(?:$|名稱:)) 是整個片段(?=) 是右斷言,(?:)是不進行捕獲的分組 去掉 ?: ($|名稱:) 就是字元串結尾,或名稱:字元比對(摘自留言回複)

使用js來測試一下

var re = '(名稱):([^,]*?),(作者):([^,]*?),(ISBN):([^,]*?),(出版社):([^,]*?)(?=(?:$|名稱:))';
var str = '名稱:量子力學教程,作者:周世勳,ISBN:9787040262780,出版社:高教名稱:量子力學教程(第二版)學習指導,作者:倪緻祥,ISBN:9787040303506,出版社:高教';
var m = str.match(new RegExp(re,'gi'));
for(var i=0;i<m.length;i++){
    console.log(new RegExp(re,'gi').exec(m[i]));
}
           
文盲的正規表達式入門,實戰篇(歡迎提問,持續更新)如何寫出正則?

 很簡單的就能完成比對提取需求了

密碼複雜度驗證正則

然後,又一個很常用的正則驗證需求,帶有複雜度要求的密碼驗證 ^v^

一般來說,密碼要求的字元是:字母數字以及其他各種字元(ascII32-127),多少多少位長度

但現在由于各種密碼洩露很多早期密碼都被人做成詞典了,是以,很久之前,對密碼就有了複雜度要求,比如

由字母大寫,字母小寫,數字,符号組成,至少包含三種類型,長度8-16,我們就按照這個來實作正則吧

首先,确定字元串長度

^[\u0020-\u007f]{8,16}$

然後,我們使用斷言的方式來判斷密碼字元串中包含了幾種邏輯

^(?=.*?[0-9])[\u0020-\u007f]{8,16}$

(?=.*?[0-9]) 表示後續字元串中有數字

(?=.*?[a-z]) 表示後續字元串中有小寫字母

(?=.*?[A-Z]) 表示後續字元串中有大寫字母

(?=.*?[^a-zA-Z0-9]) 表示後續字元串中有字母數字以外的符号

現在需要密碼中至少包含三種邏輯。。。Hmmmmm

完全符合四個要求的正則很容易實作

^(?=.*?[0-9])(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[^a-zA-Z0-9])[\u0020-\u007f]{8,16}$

直接用四次斷言判斷即可,但如果隻實作其中一種呢。。。。Hmmmm

^((?=.*?[0-9])|(?=.*?[a-z])|(?=.*?[A-Z])|(?=.*?[^a-zA-Z0-9]))[\u0020-\u007f]{8,16}$

符合一個條件的也好弄,直接在斷言裡面加或的關系。。。

那麼,通過斷言的不同組合,就可以得到符合三種條件的正則了

^((?=.*?[0-9])(?=.*?[a-z])(?=.*?[A-Z])|(?=.*?[0-9])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[^a-zA-Z0-9]))[\u0020-\u007f]{8,16}$

這個正則到是能判斷至少符合三個規則的密碼複雜度。。。。但也太累贅了,如果複雜度要求變了,有更多的條件,比如字母中至少含有asdfg中的一個,字母中至少包含yuiop中的一個。。。。總的條件數程式設計了六個,至少包含三個的話。。。正則沒法看了,是以,對于驗證來說,有些可以用正則,有些則不要用正則了,用個程式随便判斷下,都比純正則簡單了



           

提取html标簽外(正文中)的内容

(2021-07-27 更新)

我們有任意html,通常是通過采集獲得的,那麼有這麼個字元串,我們要比對其中的内容,有時候會比對的比我們預期的内容要多,比如比對一個包含 style 單詞的片段

style="[^"]*"
           

結果就會發現,比對出來了N多N多的資訊,但絕大部分是我們不關注的,因為他們來自标簽的屬性,而我們需要的是正文中相關的内容,用右斷言會非常簡單的解決這個問題

style="[^"]*"(?=[^>]*?<)
           

前邊内容不變,右邊我們隻需要判斷,在下一個左尖括号前,沒有出現右尖括号。嗯嗯,多簡單,邏輯一下子就清晰了。至于為什麼是這個邏輯,就不細講了,大家都知道,一對尖括号就是一個标簽嘛。

-------------------------------------------------------

那麼,本文将持續更新,有正則問題的,可以在發個留言哦,如果問題很有代表性,就更新到正文内哦

繼續閱讀