正則表達式-郵箱正則解析引導

1亭引,強推一個github上學習正則的項目

? ? ? https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md

2侧啼,常見的郵箱格式

? ? 1渣触,數字 + @ + 數字 + .com:111222335556666@163.com

? ? 2戳护,數字湘今、字母 + 下劃線 + @ + 數字|字母 + .com:zhangsan_123@163(qq).com

? ? 3岔擂,數字病苗、字母、下劃線 + @ + 數字挠阁、字母宾肺、中劃線- + .com:zhangsan_123@company-china.com

? ? 補充說明:為了下文便于理解,假定上述郵箱字符串作以下拆分:

? ? ? ? 1)第一部分:@符號之前的內容

? ? ? ? 2)第二部分:@符號之后侵俗,.符號之前的部分

? ? ? ? 3)第三部分:.符號之后的部分(雖然上述鏈接格式是以頂級域名com為結尾锨用,但并不排除出現類似.com.cn這樣的結構)

3,正則解析

????3.0隘谣,前言? ? ? ??

? ? ?????????1增拥,基于每個人的思維模式,理解能力等因素寻歧,為了使您的正則學習不誤入歧途跪者,請確保在參考了一定資料(如菜鳥教程、或是上述推薦的github項目)之后熄求,有了初步的基礎后,再參考本文逗概,作進一步的參考印證會更好一點弟晚,請認真考慮我的提議!

? ? ? ? ? ? 2逾苫,本文適合正則初學者閱讀卿城;本意還是為了引導初學者在學習過程中如何去思考構造及優(yōu)化正則表達式;本文所用的例子并不一定全部涵蓋現實中所有的郵箱格式铅搓。

? ? ? ? ? ? ? ? ?故在閱讀過程中瑟押,希望您可以嘗試考慮本文沒有提及的地方,以及該如何優(yōu)化星掰?同時多望,也歡迎您在下方留言處予以指正嫩舟,非常感謝!

? ? ? ? ? ? 3怀偷,本文篇幅略長家厌,您最好是有時間了跟著操作一遍比較好。

? ? ? ? ? ? 4椎工,部分元字符因為偷懶的緣故饭于,并未一一列出,請綜合參考各方資料维蒙。

? ? 3.1掰吕,思考題:如何(僅)匹配數字或字母其中一種情況?

? ? ? ? ? ? 1颅痊,會的同學請略過

? ? ? ? ? ? 2殖熟,相關元字符:

?????????????????????\d? ?-? 表示[0-9]的整數數字;? ? ? ? ? ? ? ? ?

????????????????????\w? -? 表示字母八千、數字吗讶、下劃線

? ? ? ? ? ? ????????+? ?-? 表示該符號(即符號+)前出現的子表達式需要至少出現1次父虑;

????????????????????*? ?-? ?表示該符號前出現的子表達式需要至少出現0次

? ? ? ? ? ? ????????材部? -? ?表示該字符前出現的子表達式可以出現0次或1次

? ? ? ? ? ? ????????^? ?-? ?匹配輸入字符的開始位置

? ? ? ? ? ? ? ? ? ? $? ?-? ?匹配輸入字符的結束位置

? ? ? ? ? ? ? ? ? ? ?:? -? ?匹配 pattern 但不獲取匹配結果

? ??????????????????x|y: -? 匹配x或匹配y

? ? ? ? ? ? ? ? 針對上述思考題,我將嘗試分步進行校驗:

? ? ? ? ? ? ? ? 1)如何僅匹配數字谤民?

? ? ? ? ? ? ? ? ? ? 匹配單個整數的元字符是\d沸停,匹配多個整數數字字符串可以用\d+(當然膜毁,*其實也是可以的,顯然元字符+的匹配結果是元字符*的匹配結果的子集)愤钾;那如何保證整個字符串只能出現數字呢瘟滨?答案是用元字符^和$去限制輸入值;

? ? ? ? ? ? ? ? ? ? 也即是說能颁,^與\d結合告訴程序需要排除輸入字符的開始位置不為數字的情況($符號同理)杂瘸。

????????????????????同時滿足這兩個限制才會輸出匹配結果(至于中間不為數字的情況嘛,該表達式走不下去伙菊,因為當判斷到非數字的情況的時候败玉,意味著\d+匹配結束,然后$符號發(fā)現結束位置不為數字镜硕,匹配失斣艘怼;您可以試著解除$元字符的限制兴枯,看看中間不為數字的匹配結果)血淌。

? ? ? ? ? ? ? ? 2)如何僅匹配字母?

? ? ? ? ? ? ? ? ? ? ? 構造過程同上财剖。需要注意的是悠夯,在當前限制下癌淮,\w不再適合用來匹配字母,因為\w同時還能匹配數字和下劃線疗疟。

所以我嘗試將之替換為[a-zA-Z]该默。

? ? ? ? ? ? ? ? 3)如何(僅)匹配數字或字母其中一種情況?

? ? ? ? ? ? ? ? ? ? ? 將前兩步的結果策彤,構造成x|y形式栓袖。

? ? ? ? ? ? ? ? 4)針對第3步的結果,該如何優(yōu)化店诗?

? ? ? ? ? ? ? ? ? ? ? 需要提醒的是裹刮,由于第3步中,我將第1步和第2步中的結果組成了“x|y”這種形式庞瘸,為了不使這兩個子表達式造成歧義捧弃,我用了兩個小括號將其包裹起來;

? ? ? ? ? ? ? ? ? ? ? 于是我面臨了一個問題:由于小括號除了通俗意義上的隔離擦囊、提高優(yōu)先級等作用外违霞;它在正則里還有一個作用是收集并存儲括號內子表達式的匹配結果。因此瞬场,當我并不需要這個子表達式的匹配結果時买鸽,我可以用元字符“?:”來實現這個想法。當然贯被,如果您需要用到的話眼五,則并不需要考慮?:元字符的作用。

? ? 3.2彤灶,數字 + @ + 數字 + .com類:

? ? ? ?相關元字符:

????????????\d? ?-? 表示[0-9]的整數數字看幼;

????????????\w? -? 表示字母、數字幌陕、下劃線

? ? ? ? ? ? +? ?-? 表示該符號(即符號+)前出現的子表達式需要至少出現1次诵姜;

????????????*? ?-? ?表示該符號前出現的子表達式需要至少出現0次

? ? ? ? ? ? ? -? ?表示該字符前出現的子表達式可以出現0次或1次

? ? ? ? ? ? ^? ?-? ?略

? ? ? ? ? ? .? ?-? ? 略

? ???????????:? -? ?匹配 pattern 但不獲取匹配結果

? ? ? ? ? ? 雖然常規(guī)下搏熄,使用+ 和 * 是為了讓符號前的最后一個字符出現多次茅诱,例如,zo+里搬卒,+號所應用的字符就是o,而不是zo翎卓,所以zo+這個正則契邀,回去匹配zo,zoo失暴,zo...坯门,卻不會去匹配zozo微饥;

? ? ? ? ? ? 但上述表述中,之所以描述為菜鳥教程里表述的“子表達式”古戴,是因為“字符”的概念并不同于常規(guī)意義下的char欠橘,我是可以通過小括號()去構造新的“字符”的(而常規(guī)意義下,超出一個char的字符现恼,再表述為字符就有點歧義了肃续,所以在初學階段,理解為子表達式會更合適一點)叉袍;這意味著始锚,我要向匹配zozo的話,可以用正則表達式(zo)+

????????????雖然上述想盡可能去解釋清楚這個概念喳逛,但為了防止誤解瞧捌,或是為了加深印象,您最好可以多做嘗試润文。

????????????所以上述正則可以對號入座:/\d+@\d+.\w+/

? ? ? ? ? ? 在優(yōu)化上述正則前姐呐,我想就@和.這樣的字符引申出一個概念:在無解的情況下,可以使用通俗語言表達形式去構造正則典蝌;

? ? ? ?????原因是如下:

? ? ? ? ? ?1)曙砂,某些符號在不具備很強復用性的情況下是沒有簡寫形式的,這也是為什么對于[a-zA-Z0-9_]這個正則可以用 \w來替代赠法;(當然麦轰,基于下劃線都被丟到\w來看,哪天@符號被丟進去倒也不奇怪砖织,畢竟字母和數字也沒很強的關聯不是款侵?)

? ? ? ? ? ?2),在精通之前侧纯,您最好做好先初步構造新锈,再嘗試優(yōu)化這一流程的心理準備;比如上述正則還可以更粗糙一點: /\d+@\d+.com/(雖然這樣一來眶熬,就屏蔽了.org妹笆,.cn這類的頂級域名)

? ? ? ? ????那么對上述正則,可以如何優(yōu)化呢娜氏?

? ? ? ? ? ? 1)@符號前有個\d+拳缠,@符號后有個\d+,那能不能將他們合在一起呢贸弥?

? ? ? ? ? ? 這種思路是可以的窟坐,主要在于@符號如何處理呢?可以考慮用元字符“?"來標識它可出現可不出現。然后為了保證合并后的子表達式出現兩次哲鸳,我需要將其用小括號包裹臣疑,并用+號來對他進行擴展(其實*號也可以,畢竟考慮到子表達式需要出現2次徙菠,那么>=0和>=1在這種情況下就沒什么區(qū)別了)讯沈;于是我得到了新的正則?/(\d+@?)+.\w+/

? ? ? ? ? ? 2)雖然我在優(yōu)化1)處用小括號對@符號的前后進行了整合,但小括號有個特性—對括號內的子表達式進行收集和存儲婿奔,于是缺狠,我得到了下邊的結果:? ? ? ?

/(\d+@?)+.\w+/的匹配結果

? ? ? ? ? ? 對于上述結果,您可以用(?:pattern)表達式來進行設定脸秽,它的含義是儒老,匹配pattern部分的內容,但是记餐,不緩存其匹配結果驮樊。基于對該元字符的應用片酝,我得到了如下結果:

/(?:\d+@?)+.\w+/的匹配結果

? ? ? ? ? ? 3)對于上述正則表達式囚衔,您也許會發(fā)現,其對郵箱的起始字符未限定

? ? ? ? ? ? ps:我當前是在基于對“數字 + @ + 數字 + .com”這一類郵箱做處理雕沿,所以按照這類郵箱的定義练湿,是不應該出現出現非數字的情況的);所以有了如下結果:

/(?:\d+@?)+.\w+/的匹配結果

? ? ? ? ? ? 實際上這種已經不符合第一種郵箱格式了审轮,為了排除這種可能肥哎,我不得不考慮在首位加個符號^以標識郵箱是以數字開始輸入的:/^(?:\d+@?)+.\w+/

? ? ? ? ? ? 4)然后我發(fā)現,上述表達式有一個嚴重的bug - 對于符號“.”沒有進行轉義

? ? ? ? ? ? 于是出現了以下錯誤的(?)匹配結果:

沒有轉義的元字符.引發(fā)的異常匹配-1

? ? ? ? ? ? ?那么上述錯誤是怎么發(fā)生的呢疾渣?

? ? ? ? ? ? ?您可以嘗試從結果一步步逆推回去篡诽。當然,我當前也是如此做的榴捡,比方說111222335556666@這個數字部分說明第一部分的\d+是生效了的,同時元字符杈女?對其前面的子表達式(即@部分)可出現0次或1次的表述,使得結果里第一部分數字后跟著一個@吊圾;至此第一部分的數字和@符號匹配完畢达椰;

? ? ? ? ? ? ?緊接著應該匹配第二部分的數字,從結果可知项乒,第二部分的\d+匹配到了163啰劲,@沒出現是因為元字符?標識它可以不出現檀何。

? ? ? ? ? ? ?那么上述異常結果中蝇裤,wwww是怎么來的呢趁尼?

? ? ? ? ? ? ?其原因是元字符.沒有做轉義,而元字符.的含義是匹配除換行符和回車符之外的任意單個字符猖辫。從結果來看,由于元字符.緊跟在匹配數字的正則子表達式之后砚殿,于是它順利匹配到了163之后的單個字符w啃憎;而剩下的3個www則是由\w+完成的匹配。

? ? ? ? ? ? ?上述錯誤得出的教訓:1似炎,盡可能熟悉每個元字符的含義辛萍;2,該轉義的字符千萬別漏了羡藐。

? ? ? ? ? ? ?上述錯誤修正后的結果:/(?:\d+@?)+\.\w+/

? ? ? ? ? ? ?上述錯誤的同類結果:? ? ? ? ? ? ? ? ? ? ? ?

沒有轉義的元字符.引發(fā)的異常匹配-2

? ? ? ? ? ? ? 它出現的原因大體同上贩毕,但上述結果的出現有一個地方需要重點說明下:正則表達式默認是貪婪匹配模式,這意味著仆嗦,(假如您大致懂一點回溯的內容的話)辉阶,一次能到終點的操作,它絕對不會回溯一次另外選一條路走瘩扼!這一點很重要谆甜!

? ? ? ? ? ? ? 這導致了上述表達式中(?:\d+@?)+這個部分只執(zhí)行了一次,得到了結果“111222335556666@”集绰;然后緊跟其后的元字符.匹配到了w规辱;然后由于元字符\w表述了字母、數字栽燕、下劃線三種概念罕袋,于是它跟元字符+一起,匹配到了最后的www163 部分碍岔。關于上述結果的驗證過程浴讯,可以考慮將正則的\w+部分去掉,您會發(fā)現付秕,結果是“111222335556666@w”兰珍。

? ? ? ? ? ? ? 也許您可以試著分析下如下兩個字符串的匹配結果:

? ? ? ? ? ? ? “111222335556666wwwww@163.com”

? ? ? ? ? ? ? “11122233wwww5556666@163.com”

? ? ? ? ? ? 5)然后我發(fā)現,第4步中得到的結果還有瑕疵 - \w 除了字母询吴,還能匹配數字和下劃線

? ? ? ? ? ? ? ? ? 于是下邊的錯誤也就發(fā)生了:

\w+并不適合用來匹配純字母組成的域名部分

? ? ? ? ? ? ? ? ? ?為了修正錯誤:我將表達式調整為/(?:\d+@?)+\.[a-zA-Z]+/(當然掠河,假設有人把域名寫成COm這種形式,我建議還是整體對郵箱字符串做一下toUpperCase或者toLowerCase比較好猛计!雖然是可以做進一步拆分校驗唠摹,但嚴格來說,這并不屬于校驗不合法的范疇)

? ? ? 3.3奉瘤,數字勾拉、字母 + 下劃線 + @ + 數字|字母 + .com:

????????????相關元字符:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

????????????????\w? -? 表示字母煮甥、數字、下劃線

? ? ? ? ? ? ????+? ?-? 表示該符號(即符號+)前出現的子表達式需要至少出現1次藕赞;

????????????????*? ?-? ?表示該符號前出現的子表達式需要至少出現0次

? ? ? ? ? ? ????成肘? -? ?表示該字符前出現的子表達式可以出現0次或1次

? ? ? ? ? ? ????^? ?-? ?略

? ? ? ? ? ? ????.? ?-? ? 略

? ? ? ? ? ? ? ? 經過上述3.1部分的啰里吧嗦,我想初步的正則表達式并不難配斧蜕,對吧双霍。

? ? ? ? ? ? ? ? 比如:/^(?:\w+@?)+\.[a-zA-Z]+/

? ? ? ? ? ? ? ? 接著,請跟我一起來拆解下上述的表達式:

? ? ? ? ? ? ? ? ? ? 1)^(?:\w+@?)+:表述了我想匹配以\w開頭批销,且形如:zhangsan_1@163(qq)這樣格式的字符串

? ? ? ? ? ? ? ? ? ? 2)\.:表述匹配普通字符.

? ? ? ? ? ? ? ? ? ? 3)[a-zA-Z]+: 最后一部分\w+表述我想匹配最后的域名部分(當然洒闸,形如.com.cn暫時不在討論范圍內)

? ? ? ? ? ? ? ? 通過拆解表達式,您可以發(fā)現均芽,上述部分出現了3.2中第5步的錯誤丘逸,即\w并不光匹配字母、數字掀宋,還匹配下劃線深纲。

????????????????而下劃線出現在第一部分,即@符號之前布朦,可以說是符合本回合郵箱構造規(guī)則囤萤;但是,若出現在@符合之后的第二部分是趴,那就大為不妥了涛舍,而上述表達式顯然,會出現以下匹配結果:

/^(?:\w+@?)+\.\w+/表達式的異常匹配-1
/^(?:\w+@?)+\.\w+/表達式的異常匹配-2

? ? ? ? ? ? ? ? 由于上述的表達式對于第二部分內容(@字符之后唆途,.字符之前)富雅,匹配的并不盡如人意。所以子表達式“^(?:\w+@?)+”需要對第二部分的匹配進行優(yōu)化肛搬。

? ? ? ? ? ? ? ? 既然問題出在第二部分没佑,那么意味著,我在3.2中分析時温赔,對@符號前后子表達式的整合(即將xx@xx整合為(xx@?)+這種形式)就不攻自破了蛤奢。

????????????????那么,對于第二部分的匹配期望陶贼,我現在需要構造一個正則表達式啤贩,使得能且僅能匹配(純數字或純字母表達式的)其中一種情況,即要么匹配類似ww這樣的字符串拜秧,要么匹配111這樣的字符串痹屹,其他字符串暫且假定非法。

? ? ? ? ? ? ? ? 于是枉氮,您會發(fā)現志衍,我在3.1中已經引導您做過類似的校驗暖庄。然后,您可能會犯我之前犯過的錯誤楼肪,即簡單粗暴地將其添加到正則表達式中培廓,形成這樣的式子:/^\w+@(?:^\d+$|^[a-zA-Z]+$)\.[a-zA-Z]+/;

? ? ? ? ? ? ? ? 然后您會發(fā)現,這下不僅僅是錯誤的字符串無法通過校驗春叫,正確的字符串也不行了医舆!

? ? ? ? ? ? ? ? 于是,我希望您能跟我一起來重溫一下元字符^和元字符$的概念:前者匹配輸入的起始位置象缀,后者匹配輸入的結束位置;所以爷速,這就是我在3.1中加入起始和結束元字符可以生效央星,而在3.3中失效的原因(因為對于輸入者而言,可以人為的理解某一段輸入值的開始和結束位置惫东,但對于程序而言莉给,字符串的起始和結束位置是相對于整體而言的,而非局部的某個子串廉沮。)

? ? ? ? ? ? ? ? 基于上述反思颓遏,較為合理的一個正則表達式為:/^\w+@(?:\d+|[a-zA-Z]+)\.[a-zA-Z]+/

? ? ? ? ? ? 3.4,待續(xù)......

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末滞时,一起剝皮案震驚了整個濱河市叁幢,隨后出現的幾起案子,更是在濱河造成了極大的恐慌坪稽,老刑警劉巖曼玩,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異窒百,居然都是意外死亡黍判,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門篙梢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顷帖,“玉大人,你說我怎么就攤上這事渤滞”岫眨” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵蔼水,是天一觀的道長震糖。 經常有香客問我,道長趴腋,這世上最難降的妖魔是什么吊说? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任论咏,我火速辦了婚禮,結果婚禮上颁井,老公的妹妹穿的比我還像新娘厅贪。我一直安慰自己,他們只是感情好雅宾,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布养涮。 她就那樣靜靜地躺著,像睡著了一般眉抬。 火紅的嫁衣襯著肌膚如雪贯吓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天蜀变,我揣著相機與錄音悄谐,去河邊找鬼。 笑死库北,一個胖子當著我的面吹牛爬舰,可吹牛的內容都是我干的。 我是一名探鬼主播寒瓦,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼情屹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杂腰?” 一聲冷哼從身側響起垃你,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喂很,沒想到半個月后蜡镶,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡恤筛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年官还,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毒坛。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡望伦,死狀恐怖,靈堂內的尸體忽然破棺而出煎殷,到底是詐尸還是另有隱情屯伞,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布豪直,位于F島的核電站劣摇,受9級特大地震影響,放射性物質發(fā)生泄漏弓乙。R本人自食惡果不足惜末融,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一钧惧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勾习,春花似錦浓瞪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至艺栈,卻和暖如春英岭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背湿右。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工巴席, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诅需。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像荧库,于是被迫代替她去往敵國和親堰塌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354