《大數(shù)據(jù)分析:基于Python》 課件 第9章 正則表達(dá)式與格式化輸出_第1頁
《大數(shù)據(jù)分析:基于Python》 課件 第9章 正則表達(dá)式與格式化輸出_第2頁
《大數(shù)據(jù)分析:基于Python》 課件 第9章 正則表達(dá)式與格式化輸出_第3頁
《大數(shù)據(jù)分析:基于Python》 課件 第9章 正則表達(dá)式與格式化輸出_第4頁
《大數(shù)據(jù)分析:基于Python》 課件 第9章 正則表達(dá)式與格式化輸出_第5頁
已閱讀5頁,還剩25頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

大數(shù)據(jù)分析:基于Python

第9章

正則表達(dá)式與格式化輸出余本國正則表達(dá)式通常被用來檢索、替換那些匹配某個模式的文本,如查找和提取某個網(wǎng)頁中所有的Email或者電話號碼、網(wǎng)址等。Python中正則表達(dá)式的模塊為re,用importre導(dǎo)入。它是一種用來匹配字符串的強(qiáng)有力武器。其設(shè)計思想是用一種描述性的語言來給字符串定義一個規(guī)則,凡是符合規(guī)則的字符串,就認(rèn)為它“匹配”上了,否則該字符串就不合規(guī)。如在網(wǎng)上填表時,經(jīng)常需要填寫手機(jī)號碼,當(dāng)只有輸入正確的格式時才被接收,如第一位是1,總共11位數(shù)字,這就是用正則表達(dá)式去匹配數(shù)字。9.1元字符在python的正則模塊里,一個數(shù)字可以用“\d”匹配;一個既可以是字母又可以是數(shù)字,則可以用“\w”匹配,如身份證的最后一位;“.”可以匹配任意字符。先來看看如下的匹配模式。'00\d':可以匹配'007',但無法匹配'00A',也就是說’00’后面只能是數(shù)字;'\d\d\d':可以匹配'010',只可匹配三位數(shù)字;'\w\w\d':可以匹配'py3',前兩位可以是數(shù)字或字母,但是第三位只能是數(shù)字,如a12、3a1、223,但不可以匹配y1w或者27f。'py.':可以匹配'pyc'、'py2'、'py!'等等,最后一位可以是任意的字符。像上面這樣“.”“\w”“\d”等有特殊用途、不代表其本身字符意義的符號稱之為元字符。利用元字符進(jìn)行組合可以匹配各種字符串。常用的元字符如下表9-1所示。在正則表達(dá)式中,用*表示任意個字符(包括0個),用+表示至少一個字符,用?表示0個或1個字符,用{n}表示n個字符,用{n,m}表示n~m個字符。下面看一個復(fù)雜的例子:\d{3}\s+\d{3,8}。從左到右解讀如下。(1)\d{3}表示匹配3個數(shù)字,如'010'。(2)\s可以匹配一個空格(也包括Tab等空白符),所以\s+表示至少有一個空格,如匹配'',''等。(3)\d{3,8}表示匹配3~8個數(shù)字,如'1234567'。綜合以上,上述正則表達(dá)式可以匹配以任意個空格隔開的帶區(qū)號為3個數(shù)字、號碼為3~8個數(shù)字的電話號碼,如'0218234567'。如果要匹配'010-12345'這樣的號碼呢?因?yàn)?-'是特殊字符,在正則表達(dá)式中,要用'\'轉(zhuǎn)義,所以正則式是\d{3}\-\d{3,8}。但是,仍然無法匹配'010-12345',因?yàn)?-'兩側(cè)帶有空格,所以需要更復(fù)雜的匹配方式。要做更精確的匹配,可以用[]表示范圍。[0-9a-zA-Z\_]可以匹配一個數(shù)字、字母或者下畫線。[0-9a-zA-Z\_]+可以匹配至少由一個數(shù)字、字母或者下畫線組成的字符串,如'a100','0_Z','Py3000'等。[a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下畫線開頭,后接任意個由一個數(shù)字、字母或者下畫線組成的字符串,也就是Python合法的變量。[a-zA-Z\_][0-9a-zA-Z\_]{0,19}更精確地限制了變量的長度是1~20個字符(前面1個字符+后面最多19個字符)。A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'。^表示行的開頭,^\d表示必須以數(shù)字開頭。$表示行的結(jié)束,\d$表示必須以數(shù)字結(jié)束。需要注意,py也可以匹配'python',但是加上^py$就變成了整行匹配,就只能匹配'py'了。如匹配文本“eamil120487362@1234”中的Email正則表達(dá)式,則匹配模式為:\b[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,4}\b,具體的表達(dá)式解析如下圖.9.2re模塊及其函數(shù)Python提供re模塊,其包含所有正則表達(dá)式的功能,在使用時先使用importre導(dǎo)入。由于Python的字符串本身也用\轉(zhuǎn)義,所以要特別注意。s='ABC\\-001'正則表達(dá)式對應(yīng)的字符串變成:'ABC\-001'。因此強(qiáng)烈建議使用Python的r做前綴,這樣就不用考慮轉(zhuǎn)義的問題。s=r'ABC\-001'正則表達(dá)式對應(yīng)的字符串仍是:'ABC\-001'。先看看正則表達(dá)式如何匹配字符串,代碼如下。In[1]:importreIn[2]:re.match(r'^\d{3}\-\d{3,8}$','010-12345')<_sre.SRE_Matchobject;span=(0,9),match='010-12345'>In[3]:re.match(r'^\d{3}\-\d{3,8}$','01012345')re.match()總是從字符串的開頭位置開始查找匹配,并返回匹配到的字符串的match對象(匹配對象)<class'_sre.SRE_Match'>,如果不是在起始位置或者匹配不到,match()函數(shù)將返回None。re.match()匹配成功返回的結(jié)果是match對象,有三部分,匹配的結(jié)果是第三部分match的值,第二部分表示匹配到的起止范圍span,如In[2]返回的結(jié)果第二部分span=(0,9)。也可直接使用group()方法直接返回匹配結(jié)果。In[4]:re.match(r'^\d{3}\-\d{3,8}$','010-12345').group()Out[4]:'010-12345're.match()函數(shù)格式如下。re.match(pattern,string)pattern:匹配模式。string:被匹配的文本或字符串。In[5]:test='用戶輸入的字符串'ifre.match(r'正則表達(dá)式',test):print('ok')else:print('failed')Out[5]:Failed9.2.1分組除了簡單地判斷是否匹配之外,正則表達(dá)式還有提取子串的強(qiáng)大功能。用()表示的即為要提取的分組(Group)。例如:^(\d{3})-(\d{3,8})$分別定義了兩個組,可以直接從匹配的字符串中提取出區(qū)號和本地號碼。In[1]:importrem=re.match(r'^(\d{3})-(\d{3,8})$','010-12345')

mOut[1]:<_sre.SRE_Matchobject;span=(0,9),match='010-12345'>In[2]:m.group(0)Out[2]:'010-12345'In[3]:m.group(1)Out[3]:'010'In[4]:m.group(2)Out[4]:'12345'如果正則表達(dá)式中定義了組,就可以在match對象上用group()方法提取子串。注意到group(0)是原始字符串,group(1)、group(2)……表示第1、2……個子串。提取子串非常有用,舉例如下。In[5]:t='19:05:30'm=re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$',t)In[6]:m.groups()Out[6]:

('19','05','30')這個正則表達(dá)式可以直接識別合法的時間。但有些時候,用正則表達(dá)式也無法做到完全驗(yàn)證,識別日期模式如下。'^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'對于'2-30'和'4-31'這樣的非法日期,用正則還是識別不了,或者說寫出來非常困難,這時就需要程序配合識別了。9.2.2切分字符串用正則表達(dá)式切分字符串比用固定的字符更靈活,一般切分方法如下。In[1]:'abc'.split('')Out[1]:['a','b','','','c']執(zhí)行上面代碼結(jié)果顯示,無法識別連續(xù)的空格。運(yùn)行正則表達(dá)式結(jié)果如下。In[2]:importrere.split(r'\s+','abc')Out[2]:['a','b','c']無論多少個空格都可以正常分割。加入“\,”試看結(jié)果。In[3]:re.split(r'[\s\,]+','a,b,cd')Out[3]:['a','b','c','d']再加入“\,\;”試試。In[4]:re.split(r'[\s\,\;]+','a,b;;cd')Out[4]:['a','b','c','d']如果用戶輸入了一組標(biāo)簽,可以用正則表達(dá)式把不規(guī)范的輸入轉(zhuǎn)化成正確的數(shù)組。9.2.3re.search()函數(shù)re.search()函數(shù)對整個字符串進(jìn)行搜索匹配,返回第一個匹配到的字符串match對象。格式如下。re.search(pattern,string[,flags=0])pattern:匹配模式,由pile獲得。string:被匹配的文本或字符串。re.search()函數(shù)和re.match()函數(shù)類似,不過re.search()函數(shù)不會限制只從字符串開頭位置匹配。In[1]:importrem21=re.search(r'rat','dogratdog')

m21Out[1]:<re.Matchobject;span=(4,7),match='rat'>然而re.search()函數(shù)匹配到第一個匹配項(xiàng)之后便停止繼續(xù)查找,當(dāng)在'dogratdog'字符串中用re.search()函數(shù)查找'dog'時,返回其首次匹配到的位置。In[2]:m22=re.search(r'dog','dogratdog')m22Out[2]:<re.Matchobject;span=(0,3),match='dog'>re.search()函數(shù)和re.match()函數(shù)返回的match對象,實(shí)際上是一個關(guān)于匹配子串的包裝類。前面我們看到可以通過調(diào)用group()函數(shù)得到匹配的子串,但是匹配對象還包含了更多關(guān)于匹配子串的信息。例如,match對象可以告訴我們,匹配的內(nèi)容在原始字符串中的開始位置和結(jié)束位置。In[3]:m0=re.search(r'dog','dogratdog')

m0.start()Out[3]:0

In[4]:m0.end()Out[4]:39.2.4re.findall()函數(shù)其實(shí)在很多匹配查找時,想得到所有匹配到的結(jié)果,而不是僅得到第一個匹配到的match對象,此時就需要使用re.findall()函數(shù)。當(dāng)我們調(diào)用re.findall()函數(shù)時,可以非常簡單地得到一個所有匹配模式的列表。In[1]:importrere.findall(r'dog','dogratdog')Out[1]:['dog','dog']

In[2]:re.findall(r'rat','dogratdog')Out[2]:['rat']

re.findall()函數(shù)是我們使用的最多的一種匹配模式。9.2.5pile()函數(shù)pile()函數(shù)編譯正則表達(dá)式模式,返回一個對象??梢园殉S玫恼齽t表達(dá)式編譯成正則表達(dá)式對象,方便后續(xù)調(diào)用及提高效率。pile(pattern,flags=0)pattern:指定編譯時的表達(dá)式字符串。flags:編譯標(biāo)志位,用來修改正則表達(dá)式的匹配方式。支持re.L|re.M同時匹配flags標(biāo)志位參數(shù)。●re.I(re.IGNORECASE):使匹配對大小寫不敏感。●re.L(re.LOCAL):做本地化識別(Locale-aware)匹配。●re.M(re.MULTILINE):多行匹配,影響^和$。●re.S(re.DOTALL):使.匹配包括換行在內(nèi)的所有字符?!駌e.U(re.UNICODE):根據(jù)Unicode字符集解析字符。這個標(biāo)志影響\w,\W,\b,\B。●

re.X(re.VERBOSE):該標(biāo)志通過給予更靈活的格式以便將正則表達(dá)式寫得更易于理解。pile()函數(shù)的用法示例如下。In[1]:importrecontent='Citizenwang,alwaysfallinlovewithneighbour,WANG'rr=pile(r'wan\w',re.I)#不區(qū)分大小寫print(type(rr))Out[1]:<class'_sre.SRE_Pattern'>In[2]:a=rr.findall(content)print(type(a))print(a)Out[2]:<class'list'>['wang','WANG']9.3貪婪匹配需要特別指出的是正則匹配默認(rèn)是貪婪匹配,也就是匹配盡可能多的字符。例如,匹配出數(shù)字后面的0。In[1]:importrere.match(r'^(\d+)(0*)$','102300').groups()Out[1]:('102300','')由于\d+采用貪婪匹配,直接把后面的0全部匹配了,結(jié)果0*只能匹配空字符串了。必須讓\d+采用非貪婪匹配(也就是盡可能少匹配),才能把后面的0匹配出來,加個?就可以讓\d+采用非貪婪匹配。In[2]:re.match(r'^(\d+?)(0*)$','102300').groups()Out[2]:

('1023','00')在數(shù)據(jù)處理過程中經(jīng)常會遇到正則表達(dá)式,尤其爬蟲數(shù)據(jù)處理,其中(.*?)的使用概率較高,以下做個說明?!?*?”表示非貪心算法,表示要精確的配對?!?*”表示貪心算法,表示要盡可能多的匹配?!?)”表示要獲取括弧之間的信息。舉個例子來說明一下。In[1]:importre...:a='wwIwwjshdwwlovewwsffawwpythonww'...:infos=re.findall('ww(.*?)ww',a)...:print(infos)

['I','love','python']由于只需要獲取()之間的數(shù)據(jù),所以最終的結(jié)果為:['I','love','python']。如果使用“.*”表達(dá)式,則表示貪婪匹配,則返回去掉頭尾ww之間的全部數(shù)據(jù)。In[2]:importre...:a='wwIwwjshdwwlovewwsffawwpythonww'...:infos=re.findall('ww(.*)ww',a)...:print(infos)['Iwwjshdwwlovewwsffawwpython']9.4字符串的替換和修改re模塊還提供了對字符串的替換和修改函數(shù),它們比字符串對象提供的函數(shù)功能要強(qiáng)大。re.sub(rule,replace,target[,count])re.subn(rule,replace,target[,count])在目標(biāo)字符串中按規(guī)則查找匹配的字符串,再把它們替換成指定的字符串。我們可以指定被替換的次數(shù),否則將替換所有匹配到的字符串。第一個參數(shù)是正則模式,第二個參數(shù)是將要被替換的新字符串,第三個參數(shù)是目標(biāo)字符串,第四個參數(shù)是被替換的次數(shù)(可省略)。這兩個函數(shù)的唯一區(qū)別是返回值。re.sub()返回一個被替換的字符串,re.subn()返回一個元組,第一個元素是被替換的字符串,第二個元素是一個數(shù)字,表明產(chǎn)生了多少次替換。例如,將下面字符串中的'dog'全部替換成'cat'。In[1]:s='Ihaveadog,youhaveadog,hehasadog're.sub(r'dog','cat',s)Out[1]:'Ihaveacat,youhaveacat,hehasacat'如果只想替換前面兩個,則可以寫如下代碼。In[2]:re.sub(r'dog','cat',s,2)Out[2]:'Ihaveacat,youhaveacat,hehasadog'或者我們想知道發(fā)生了多少次替換,則可以使用subn。In[3]:re.subn(r'dog','cat',s)Out[3]:('Ihaveacat,youhaveacat,hehasacat',3)9.5格式化輸出Python格式化輸出有兩種方式:%和format。format的功能要比%方式強(qiáng)大,其中format可以自定義字符填充空白、字符串居中顯示、轉(zhuǎn)換二進(jìn)制、整數(shù)自動分割、百分比顯示等功能。Python3.6之后新增了f格式化。9.5.1使用%符號進(jìn)行格式化首先看一個用%進(jìn)行格式化的代碼示例。In[1]:name1="Yubg"print("Hesaidhisnameis%s."%name1)Out[1]:HesaidhisnameisYubg.字符串引號內(nèi)的%為格式化開始,類似于占位符,%后的s表示占位處要填充的是字符串,若要填充整數(shù)則用d,填充浮點(diǎn)數(shù)用f。緊跟在引號之后的%表示對前面占位符處需要填充的內(nèi)容,即賦值。所以上述代碼中"Hesaidhisnameis%s."的%s表示在此處要填充字符串,填充的內(nèi)容是其后面%name1的內(nèi)容,由于name1的值是"Yubg",所以print("Hesaidhisnameis%s."%name1)這行代碼輸出的就是“HesaidhisnameisYubg.”In[1]:name1="Yubg"

print("Hesaidhisnameis%d."%name1)

Traceback(mostrecentcalllast):File"<ipython-input-1-d3549f33c4f0>",line2,in<module>print("Hesaidhisnameis%d."%name1)

TypeError:%dformat:anumberisrequired,notstr由于%d表示要填充的是數(shù)值型整數(shù),非字符串,所以此處會導(dǎo)致類型錯誤。當(dāng)有多個占位符時,則要求占位符處和賦值之間必須一一對應(yīng)。In[2]:"iam%sandageis%d"%("alex",18)Out[2]:'iamalexandageis18'也可以用字典的形式來賦值.In[2]:"iam%(name)sandageis%(age)d"%{"name":"alex","age":18}Out[2]:'iamalexandageis18'

In[3]:"percent%.2f"%99.97623Out[3]:'percent99.98'

In[4]:"iam%(pp).2f"%{"pp":123.425556}Out[4]:'iam123.43'

In[5]:"iam%(pp)+.2f%%"%{"pp":123.425556,}#兩個%%表示輸出一個%Out[5]:'iam+123.43%'9.5.2format()函數(shù)格式化除了%字符串格式化方法之外,推薦使用format()函數(shù)進(jìn)行格式化,該方法靈活,不僅可以使用位置進(jìn)行格式化,還支持使用關(guān)鍵字參數(shù)格式化。1.通過關(guān)鍵字In[1]:print('{名字}今天{動作}'.format(名字='陳某某',動作='拍視頻'))#通過關(guān)鍵字

陳某某今天拍視頻

In[2]:grade={'name':'陳某某','fenshu':'59'}print('{name}電工考了{(lán)fenshu}'.format(**grade))#字典當(dāng)關(guān)鍵字時其前加**

陳某某電工考了592.通過位置In[3]:print('{1}今天{0}'.format('拍視頻','陳某某'))#通過位置

陳某某今天拍視頻

In[4]:print('{0}今天{1}'.format('陳某某','拍視頻'))

陳某某今天拍視頻^、<、>分別表示居中、左對齊、右對齊,后面帶寬度。In[5]:print('{:^14}'.format('陳某某'))#共占位14個寬度,陳某某居中

陳某某

In[5]:print('{:>14}'.format('陳某某'))#共占位14個寬度,陳某某居右對齊

陳某某

In[7]:print('{:<14}'.format('陳某某'))#共占位14個寬度,陳某某居左對

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論