1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Python入門系列23 - 正則表達(dá)式(一)

        共 5946字,需瀏覽 12分鐘

         ·

        2019-10-14 23:21

        Python入門系列23

        505a7cb94db9e29052ae68825090ed04.webp

        正則表達(dá)式(一)


        本篇文字約為4100字,閱讀時間約為16分鐘。


        1

        前言


        今天來介紹一下Python的正則表達(dá)式。先來看下定義,何為正則表達(dá)式?


        正則表達(dá)式是一個特殊的字符序列,一個字符串是否與我們給定的這個字符序列相匹配。正則最重要的功能就是處理字符串,例如檢索你在某一段字符串中的特定單詞,或者將原來某個位置的特定字符換成你想要的字符。而對于爬蟲來說,正則表達(dá)式是必不可少的技能之一,要想正確提取源代碼中你想要的信息內(nèi)容,一般來說都會用到正則。


        2

        Python的re模塊初體驗


        這里用例子來假設(shè)一個場景吧...現(xiàn)在你正打算轉(zhuǎn)行踏入程序員的領(lǐng)域,然而面臨的第一個問題就是選擇一個主修語言來作為你轉(zhuǎn)行后的學(xué)習(xí)動力。于是有個字符串language="Java,Python,Go,Js,C,C++,PHP",你下定決心要學(xué)Python,于是讓你判斷Python這門語言是否在這個字符串中存在!你會怎么做呢?


        方案一:

        通過python內(nèi)置函數(shù)string.index('Python')


        language?=?'Java,Python,Go,Js,C,C++,PHP'
        print(language.index('Python'))

        >>> 5


        結(jié)果說明在索引下標(biāo)第5位開始,尋找到了Python字符串。


        方案二:

        通過in關(guān)鍵詞


        language?=?'Java,Python,Go,Js,C,C++,PHP'
        print('Python'?in?language)

        >>>?True


        結(jié)果說明Python字符串存在于language中。


        方案三:

        通過re模塊,需要import re。


        import?re
        language?=?'Java,Python,Go,Js,C,C++,PHP'
        """
        ???re.findall(pattern,?string,?flags=0):
        ??????必填的兩個參數(shù):
        ??????第一個參數(shù)是正則表達(dá)式的模式;
        ??????第二個參數(shù)是原字符串
        ??????選填參數(shù):flags ,傳入例如忽略大小寫的官方參數(shù)

        ???返回的結(jié)果是:?list
        """

        result?=?re.findall('Python',language)
        print(result)

        >>>?['Python']


        大家可以仔細(xì)看下代碼,注釋已經(jīng)寫得很清楚啦....使用re.findall,見名知意,是查找到所有匹配到的,所以返回的肯定是list。不信的話,我們將代碼修改一下,在language里多加一個Python,看下結(jié)果如何:

        0925a24bb857003035742affa4e79888.webp


        3

        Python正則表達(dá)式的原理性概念


        這個標(biāo)題起的名字有些拗口,因為我找不到好的概括詞語了,現(xiàn)在就來解釋一下吧....在2中我們通過re模塊來判斷了一個字符串包含不包含與原始字符串,實際上這種用法是沒有意義的,真正的正則表達(dá)式用法場景,應(yīng)該是依賴于規(guī)則!


        1. 普通字符和元字符


        還是舉例說明,還是上邊找工作的那堆語言,假設(shè)每門語言的分割,我不用逗號進(jìn)行分割了,我將各種公共電話號碼隨機(jī)插入來代替逗號,于是得到language="Java110Python120Go119Js4399C999C++666PHP"。

        需求變更了,現(xiàn)在讓你提取出電話號碼!如何去做呢?


        import?re
        language="Java110Python120Go119Js4399C999C++666PHP"
        """
        ???re.findall(pattern,?string,?flags=0):
        ??????必填的兩個參數(shù):
        ??????第一個參數(shù)是正則表達(dá)式的模式;
        ??????第二個參數(shù)是原字符串
        ??????選填參數(shù):flags,傳入例如忽略大小寫的官方參數(shù)


        ???返回的結(jié)果是:?list
        """

        result?=?re.findall('\d',language)
        print(result)

        >>>?['1',?'1',?'0',?'1',?'2',?'0',?'1',?'1',?'9',?'4',?'3',?'9',?'9',?'9',?'9',?'9',?'6',?'6',?'6']


        由于每個數(shù)字都不近相同,你可以用一堆數(shù)字去寫,但是比較麻煩。若換成字符,難不成還寫滿了你要匹配的字符嗎?所以這里提出兩個概念:普通字符和元字符。


        普通字符:re.findall('Python',language)中的'Python',就是普通字符。

        元字符:re.findall('\d',language)中的'\d',就是元字符。


        所謂的普通字符,就是你寫死了的固定字符,而元字符則不一樣,它代表的是一類的字符,而我現(xiàn)在寫的'\d'的含義就是匹配所有數(shù)字。需要注意的是,普通字符和元字符是在正則表達(dá)式中可以混合使用的!


        而我這里不會詳細(xì)的介紹每個元字符的用法,重要的是自己查閱相關(guān)文檔的方法,而非死記硬背這些元字符的含義,可以用到的時候再去查即可。這里給出相關(guān)圖吧,有興趣的可以看下:


        b98d0b48a019e75aeb89354e84f9784a.webp

        4eb499e6b6c820be6ea4e4f2c7acaa21.webp

        以上圖片原址:

        https://baike.baidu.com/item/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1700215?fr=aladdin#3


        具體使用可以自行百度查看。


        2. 字符集


        在上面的例子中,我們可以看到,正則表達(dá)式匹配完的list得到的都是一個個拆分的字符,而所謂的字符集就是匹配出來的字符集合,也就是多個字符。如下面的例子:


        import re

        words = "abz,acz,adz,aez,afz"
        result = re.findall('a[bcd]z', words)
        print(result)

        >>> ['abz', 'acz', 'adz']


        若想匹配到原字符串中的多個字符,我們可以用[]這樣的形式來匹配多個符合的內(nèi)容,而[]中的元素相互之間是的關(guān)系。a,z來限定邊界, [bcd] 則是匹配a,z中間符合的bcd的元素,所以最終得到的結(jié)果如上。


        import re

        words = "abz,acz,adz,aez,afz"
        result = re.findall('a[^bcd]z', words)
        print(result)

        >>> ['aez', 'afz']


        若在字符集的正則規(guī)定前,加上^則是代表取反的意思,可以看到結(jié)果,不匹配bcd,最終結(jié)果得到的是e,f。


        當(dāng)然還有一種寫法是下面這樣:


        import re

        words = "abz,acz,adz,aez,afz"
        result = re.findall('a[b-e]z', words)
        print(result)

        >>> ['abz', 'acz', 'adz', 'aez']


        用?-?也可以來表示一個范圍,比如A-Z,a-z,0-9等....


        3. 數(shù)量詞


        import re

        words = "I am learning Pythonnnnnn, that 's awesome!"
        result = re.findall('[a-z]{4}', words)
        print(result)

        >>> ['lear', 'ning', 'ytho', 'nnnn', 'that', 'awes']


        在字符集的基礎(chǔ)上,我們?nèi)绻胂薅ǘ嗌匍L度的字符,可以通過{}來限定匹配字符集的長度,當(dāng)我寫入4的時候,可以看到從左到右,只有當(dāng)相鄰字符組成的長度為4時,才會被匹配到。


        然而這樣匹配是沒有實際意義的,我現(xiàn)在需要的是將每個詞語拆分并且匹配到,于是有了下面的寫法:


        import?re

        words?=?"I?am?learning?Pythonnnnnn,?that?'s?awesome!"
        result?=?re.findall('[a-zA-Z]{1,11}',?words)
        print(result)

        >>>?['I',?'am',?'learning',?'Pythonnnnnn',?'that',?'s',?'awesome']


        {最短匹配長度,最長匹配長度},在配合上字符集的正則寫法,既可拆分出原有的單詞,注意的是[a-zA-Z] 這里用到了組合的寫法,匹配字符是符合大小寫a-z的。


        大家有沒有注意到一個點(diǎn),就是在數(shù)量詞這里,我對原字符串進(jìn)行正則匹配,取得長度是1~11位,那么在am時候就已經(jīng)符合一位長度了,即字母a,為什么沒有被單獨(dú)匹配出來作為結(jié)果呢?這里就涉及到下面要說的正則表達(dá)式的貪婪模式非貪婪模式了。


        4

        正則表達(dá)式的貪婪與非貪婪模式


        貪婪模式:意如其名,貪婪嘛,就是要多多多!多匹配既是王道!


        非貪婪模式:與貪婪模式相反唄,即少匹配就是王道!


        對應(yīng)上面的數(shù)量詞案例時,數(shù)量詞若是采用范圍取長度時,則是默認(rèn)使用貪婪模式,即多多匹配,所以才會看到能匹配到字符集長度多的單詞。而Python默認(rèn)傾向于是貪婪模式的!


        1.? “?” 匹配0次或者1次

        在實際的應(yīng)用中,我們也會遇到非貪婪的情況,即少匹配,那么如何書寫呢?


        import?re

        words?=?"I?am?learning?Pythonnnnnn,?that?'s?awesome!"
        result?=?re.findall('[a-zA-Z]{1,11}?',?words)
        print(result)

        >>>?['I',?'a',?'m',?'l',?'e',?'a',?'r',?'n',?'i',?'n',?'g',?'P',?'y',?'t',?'h',?'o',?'n',?'n',?'n',?'n',?'n',?'n',?'t',?'h',?'a',?'t',?'s',?'a',?'w',?'e',?'s',?'o',?'m',?'e']


        只需要在數(shù)量詞后面加一個?即可。代表的是匹配前面的數(shù)量詞0次或者1次。


        特殊的小技巧:?一般可以來去掉字符后面的重復(fù)項,例如原字符串:"Pythonnnnn",可以用 'Python?' 得到Python, 這點(diǎn)自己可以思考并實驗下。


        2.?“*” 匹配0次或者無限次


        下面這段代碼,你認(rèn)為會打印出什么樣的結(jié)果呢?


        import?re
        words?=?"I?am?learning?Pytho,Python,Pythonnnnnn,?that?'s?awesome!"
        result?=?re.findall('Pytho*',?words)
        print(result)


        輸出結(jié)果:

        >>>?['Pytho',?'Pytho',?'Pytho']


        因為在原字符串中匹配到o,后面就截止了。


        若是這樣呢:


        import?re
        words?=?"I?am?learning?Pytho,Python,Pythonnnnnn,?that?'s?awesome!"
        result?=?re.findall('Python*',?words)
        print(result)
        #輸出結(jié)果

        >>> ['Pytho',?'Python',?'Pythonnnnnn']


        匹配*號的前一個字符無限次,所以有多少n,就會被匹配到多少n。為什么'Pytho'也能被匹配到呢?因為*號代表的是前面的字符匹配到0次也是可以的!所以pytho也會被匹配到,這里需要注意。


        3. “+” 匹配1次或者無限次


        import?re

        words?=?"I?am?learning?Pytho,Python,Pythonnnnnn,?that?'s?awesome!"
        result?=?re.findall('Python+',?words)
        print(result)

        # 輸出結(jié)果
        >>> ['Python', 'Pythonnnnnn']


        +號是匹配前面的字符至少一次,或者n次。所以不會匹配到Pytho!


        4. “.” 匹配除換行符\n之外的其他所有字符


        import?re

        words?=?"Python?\n?!@#%%$*&(%)"
        result?=?re.findall('.',?words)
        print(result)

        >>>?['P',?'y',?'t',?'h',?'o',?'n',?'?',?'?',?'!',?'@',?'#',?'%',?'%',?'$',?'*',?'&',?'(',?'%',?')']


        可以看到,除了\n以外的字符都匹配到了,包括空格以及其他奇怪的字符~


        5

        正則表達(dá)式組的概念


        在說組之前,再來介紹一個正則的用法:


        ^: 匹配原字符串的首位置開始

        $: 匹配原字符串的尾位置結(jié)束


        如下事例:


        import?re

        words?=?"110120119999"
        result?=?re.findall('^\d{1,9}$',?words)
        print(result)

        >>>?[]


        因為^和$限定了原始字符串的頭和尾,從原始字符串中匹配1~9位長度的數(shù)字,并且是從頭到尾的去匹配,并沒有長度為9的數(shù)字,所以匹配出來是空的。


        正則表達(dá)式組的概念:還記得之前python的基礎(chǔ)數(shù)據(jù)類型元組嗎?正則中的組,與字符集恰好相反,字符集中匹配的字符之間是或的關(guān)系,而組中匹配的字符之間則是與的關(guān)系。


        場景如下,我現(xiàn)在想匹配整個hungry!!而若是通過字符匹配的話方法:


        import re

        words =
        "I'm hungry!!hungry!!hungry!!...."
        result = re.findall('hungry!!{3}', words)
        print(result)

        >>> []


        可以看到,什么也沒匹配到,因為現(xiàn)在寫的意思是匹配前面是hungry!!且最后一個嘆號長度為3個,也就是說如果字符串中有hungry!!!!,即可匹配到。


        cdbfbdedcc45c2f6c7b1bd9a2c2a84cf.webp


        如果想匹配到整個hungry!!并且連續(xù)的單詞出現(xiàn)3次,就要這么寫啦:


        import re

        words = "I'm hungry!!hungry!!hungry!!!!...."
        result = re.findall('(hungry!!){3}', words)
        print(result)

        >>> ['hungry!!']


        用小括號將整個單詞括起來,它就是所謂的分組了。若我要是將{3}改成{4},就會發(fā)現(xiàn),匹配不到這個結(jié)果了,因為需要組內(nèi)連續(xù)出現(xiàn)4次才可以匹配到。如下:


        2369f925b5798137a097986db93207b2.webp


        6

        總結(jié)


        今天主要介紹了python的re模塊的findall方法,此方法是入門正則表達(dá)式一個比較好的學(xué)習(xí)方式,通過各種實例可以看到最終匹配到的結(jié)果,而需要注意的點(diǎn)是:普通字符和元字符,元字符相當(dāng)于是系統(tǒng)的寫法,每種寫法代表不同的含義,在使用的時候可以將二者混合使用來達(dá)到你最終想匹配的值,現(xiàn)在也許看著正則還會有很多的疑惑,后續(xù)寫到爬蟲的時候,一講就明白了!


        至此完!


        瀏覽 109
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            午夜黄色影院 | 日本无码一区二区三三 | 国产久久久 | 男人添女人全过A片 | 少妇搡bbbb搡bbb搡一 | 少妇把腿扒开让我爽爽小说 | 色欲综合插插 | 久久久网 | 天天日天天射试看二分钟 | 国产精品久久久久婷婷二区次 |