正則表達(dá)式之所以難學(xué),是因?yàn)樗写罅康姆?hào),每個(gè)符號(hào)的意義和用法又是不一樣的,但是只要掌握了用法,正則表達(dá)式也可以很友好。 本文中所有的代碼都在python的re模塊下運(yùn)行。 定義是定義,太正經(jīng)了就沒法用了。我們來舉個(gè)栗子:假如你得到了一個(gè)網(wǎng)頁的HTML源碼。其中有一段 你想要把這個(gè)hello world提取出來,但你這時(shí)如果只會(huì)python 的字符串處理,那么第一反應(yīng)可能是 然后從這個(gè)位置向下查找到下一個(gè)<h1>出現(xiàn)這樣做未嘗不可,但是很麻煩不是嗎。需要考慮多個(gè)標(biāo)簽,一不留神就多匹配到東西了,而如果想要非常準(zhǔn)確的匹配到,又得多加循環(huán)判斷,效率太低。 這時(shí)候,正則表達(dá)式就是首選的幫手。 首先,從最基礎(chǔ)的正則表達(dá)式說起。 假設(shè)我們的想法是把一個(gè)字符串中的所有'python'給匹配到。我們?cè)囈辉囋趺醋?/p> 看完這段代碼,你是不是覺得:臥槽?這就是正則表達(dá)式?直接寫上去就行? 確實(shí),正則表達(dá)式并不像它表面上那么奇葩,如果不是我們故意改變一些符號(hào)的含義時(shí),你看到的就是想要匹配的。 所以,先把大腦清空,先認(rèn)為正則表達(dá)式就是和想要匹配的字符串長(zhǎng)得一樣。在之后的練習(xí)中我們會(huì)逐步進(jìn)化 0.無論是python還是正則表達(dá)式都是區(qū)分大小寫的,所以當(dāng)你在上面那個(gè)例子上把'python'換成了'Python',那就匹配不到你心愛的python了。 1.重新回到第一個(gè)例子中那個(gè)<h1>hello world<h1>匹配。假如我這么寫,會(huì)怎么樣? 有了入門級(jí)的經(jīng)驗(yàn),我們知道那兩個(gè)<h1>就是普普通通的字符,但是中間的是什么鬼? .字符在正則表達(dá)式代表著可以代表任何一個(gè)字符(包括它本身) findall返回的是所有符合要求的元素列表,包括僅有一個(gè)元素時(shí),它還是給你返回的列表。 機(jī)智如你可能會(huì)突然問:那我如果就只是想匹配'.'呢?結(jié)果啥都給我返回了咋整?在正則表達(dá)式中有一個(gè)字符,其實(shí)如果你編程經(jīng)驗(yàn)較多的話,你就會(huì)發(fā)現(xiàn)這是好多地方的“轉(zhuǎn)義符”。 舉個(gè)栗子,你真的想匹配'relax149137@gmail.com'這個(gè)郵箱(我的郵箱),你可以把正則表達(dá)式寫成下面這個(gè)樣子: 發(fā)現(xiàn)了吧,我們?cè)?的前面加上了轉(zhuǎn)義符,但是并不是代表匹配“.”的意思,而是只匹配“.”的意思! 不知道你細(xì)不細(xì)心,有沒有發(fā)現(xiàn)我們第一次用.時(shí),后面還跟了一個(gè)+?那這個(gè)加號(hào)是干什么的呢? 其實(shí)不難想,我們說了“.字符在正則表達(dá)式代表著可以代表任何一個(gè)字符(包括它本身)”,但是'hello world'可不是一個(gè)字符啊。 +的作用是將前面一個(gè)字符或一個(gè)子表達(dá)式重復(fù)一遍或者多遍。 比方說表達(dá)式“ab+”那么它能匹配到“abbbbb”,但是不能匹配到'a',它要求你必須得有個(gè)b,多了不限,少了不行。你如果問我有沒有那種“有沒有都行,有多少都行的表達(dá)方式”,回答是有的。 *跟在其他符號(hào)后面表達(dá)可以匹配到它0次或多次 比方說我們?cè)谕跞~內(nèi)遇到了鏈接,可能既有http://開頭的,又有https://開頭的,我們?cè)趺刺幚恚?/p> 輸出 2.比方說我們有這么一個(gè)字符串'cat hat mat qat',你會(huì)發(fā)現(xiàn)前面三個(gè)是實(shí)際的單詞,最后那個(gè)是我胡編亂造的。如果你本來就知道'at'前面是c、h、m其中之一時(shí)這才構(gòu)成單詞,你想把這樣的匹配出來。根據(jù)已經(jīng)學(xué)到的知識(shí)是不是會(huì)想到寫出來三個(gè)正則表達(dá)式進(jìn)行匹配?實(shí)際上不需要。因?yàn)橛幸环N多字符匹方式 []代表匹配里面的字符中的任意一個(gè) 還是舉個(gè)栗子,我們發(fā)現(xiàn)啊,有的程序員比較過分,,在<html></html>這對(duì)標(biāo)簽上,大小寫混用,老害得我們抓不到想要的東西,我們?cè)撛趺磻?yīng)對(duì)?是寫16*16種正則表達(dá)式挨個(gè)匹配?no 輸出 我們既然有了范圍性的匹配,自然有范圍性的排除。 [^]代表除了內(nèi)部包含的字符以外都能匹配 還是cat,hat,mat,qat這個(gè)例子,我們想匹配除了qat以外的,那么就應(yīng)該這么寫: 輸出 3.介紹到這里,我們可能已經(jīng)掌握了大致的正則表達(dá)式的構(gòu)造方式,但是我們常常會(huì)在實(shí)戰(zhàn)中遇到一些匹配的不準(zhǔn)確的問題。比方說: 輸出結(jié)果 呦呵!你咋能多了呢?我理想的結(jié)果是@hit.,你咋還給我加量了呢?這是因?yàn)檎齽t表達(dá)式默認(rèn)是“貪婪”的,我們之前講過,“+”代表是字符重復(fù)一次或多次。但是我們沒有細(xì)說這個(gè)多次到底是多少次。所以它會(huì)盡可能“貪婪”地多給我們匹配字符,在這個(gè)例子里也就是匹配到最后一個(gè)“.”。 我們?cè)趺唇鉀Q這種問題呢?只要在“+”后面加一個(gè)“?”就好了。 輸出結(jié)果 加了一個(gè)“?”我們就將貪婪的“+”改成了懶惰的“+”。這對(duì)于[abc]+,w*之類的同樣適用。 個(gè)人建議:在你使用'+',''的時(shí)候,一定先想好到底是用貪婪型還是懶惰型,尤其是當(dāng)你用到范圍較大的項(xiàng)目上時(shí),因?yàn)楹苡锌赡芩投嗥ヅ渥址貋斫o你?。?!* 為了能夠準(zhǔn)確的控制重復(fù)次數(shù),正則表達(dá)式還提供 {a,b}(代表a<=匹配次數(shù)<=b) 還是舉個(gè)栗子,我們有sas,saas,saaas,我們想要sas和saas,我們?cè)趺刺幚砟兀?/p> 輸出 如果你省略掉{1,2}中的2,那么就代表至少匹配一次,那么就等價(jià)于? 如果你省略掉{1,2}中的1,那么就代表至多匹配2次。 利用十分鐘你可以上手正則表達(dá)式,但不可能掌握它,最重要的事情是 |
|