Python 正則表達(dá)式入門(初級(jí)篇)

Python 正則表達(dá)式入門(初級(jí)篇)

本文主要為沒有使用正則表達(dá)式經(jīng)驗(yàn)的新手入門所寫。

轉(zhuǎn)載請(qǐng)寫明出處

引子

首先說 正則表達(dá)式是什么?

正則表達(dá)式道盏,又稱正規(guī)表示式疾牲、正規(guī)表示法、正規(guī)表達(dá)式戴质、規(guī)則表達(dá)式、常規(guī)表示法(英語:Regular Expression,在代碼中常簡寫為regex讨跟、regexp或RE)纪他,計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表達(dá)式使用單個(gè)字符串來描述许赃、匹配一系列匹配某個(gè)句法規(guī)則的字符串止喷。在很多文本編輯器里,正則表達(dá)式通常被用來檢索混聊、替換那些匹配某個(gè)模式的文本弹谁。

許多程序設(shè)計(jì)語言都支持利用正則表達(dá)式進(jìn)行字符串操作。例如句喜,在Perl中就內(nèi)建了一個(gè)功能強(qiáng)大的正則表達(dá)式引擎预愤。正則表達(dá)式這個(gè)概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達(dá)式通晨任福縮寫成“regex”植康,單數(shù)有regexp、regex展懈,復(fù)數(shù)有regexps销睁、regexes、regexen存崖。

引用自維基百科https://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F

定義是定義冻记,太正經(jīng)了就沒法用了。我們來舉個(gè)栗子:假如你在寫一個(gè)爬蟲来惧,你得到了

一個(gè)網(wǎng)頁的HTML源碼冗栗。其中有一段

hello world

你想要把這個(gè)hello world提取出來,但你這時(shí)如果只會(huì)python 的字符串處理供搀,那么第一反應(yīng)可能是

s ="<html><body><h1>hello world<h1></body></html>"start_index = s.find('<h1>')

然后從這個(gè)位置向下查找到下一個(gè)<h1>出現(xiàn)這樣做未嘗不可隅居,但是很麻煩不是嗎。需要考慮多個(gè)標(biāo)簽葛虐,一不留神就多匹配到東西了胎源,而如果想要非常準(zhǔn)確的匹配到,又得多加循環(huán)判斷屿脐,效率太低涕蚤。

這時(shí)候,正則表達(dá)式就是首選的幫手摄悯。

干貨開始

入門級(jí)別

接著說我們剛才那個(gè)例子赞季。我們?nèi)绻谜齽t處理這個(gè)表達(dá)式要怎么做呢?

importrekey =r"<html><body><h1>hello world<h1></body></html>"#這段是你要匹配的文本p1 =r"(?<=<h1>).+?(?=<h1>)"#這是我們寫的正則表達(dá)式規(guī)則奢驯,你現(xiàn)在可以不理解啥意思pattern1 = re.compile(p1)#我們?cè)诰幾g這段正則表達(dá)式matcher1 = re.search(pattern1,key)#在源文本中搜索符合正則表達(dá)式的部分printmatcher1.group(0)#打印出來

你可以嘗試運(yùn)行上面的代碼申钩,看看是不是和我們想象的一樣(博主是在python2.7環(huán)境下)發(fā)現(xiàn)代碼挺少挺簡單?往下看瘪阁。而且正則表達(dá)式實(shí)際上要比看起來的那種奇形怪狀要簡單得多撒遣。

首先邮偎,從最基礎(chǔ)的正則表達(dá)式說起。

假設(shè)我們的想法是把一個(gè)字符串中的所有"python"給匹配到义黎。我們?cè)囈辉囋趺醋?/p>

importrekey =r"javapythonhtmlvhdl"#這是源文本p1 =r"python"#這是我們寫的正則表達(dá)式pattern1 = re.compile(p1)#同樣是編譯matcher1 = re.search(pattern1,key)#同樣是查詢printmatcher1.group(0)

看完這段代碼禾进,你是不是覺得:臥槽?這就是正則表達(dá)式廉涕?直接寫上去就行泻云?

確實(shí),正則表達(dá)式并不像它表面上那么奇葩狐蜕,如果不是我們故意改變一些符號(hào)的含義時(shí)宠纯,你看到的就是想要匹配的。

所以层释,先把大腦清空婆瓜,先認(rèn)為正則表達(dá)式就是和想要匹配的字符串長得一樣。在之后的練習(xí)中我們會(huì)逐步進(jìn)化

初級(jí)

0.無論是python還是正則表達(dá)式都是區(qū)分大小寫的贡羔,所以當(dāng)你在上面那個(gè)例子上把"python"換成了"Python"廉白,那就匹配不到你心愛的python了。

1.重新回到第一個(gè)例子中那個(gè)<h1>hello world<h1>匹配乖寒。假如我像這么寫猴蹂,會(huì)怎么樣?

importrekey =r"<h1>hello world<h1>"#源文本p1 =r"<h1>.+<h1>"#我們寫的正則表達(dá)式宵统,下面會(huì)將為什么pattern1 = re.compile(p1)printpattern1.findall(key)#發(fā)沒發(fā)現(xiàn)晕讲,我怎么寫成findall了覆获?咋變了呢马澈?

有了入門級(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)義符”睦尽。在正則表達(dá)式里器净,這個(gè)符號(hào)通常用來把特殊的符號(hào)轉(zhuǎn)成普通的,把普通的轉(zhuǎn)成特殊的23333(并不是特殊的“2333”当凡,寫完才發(fā)現(xiàn)會(huì)不會(huì)有腦洞大的想歪了)山害。

舉個(gè)栗子纠俭,你真的想匹配"chuxiuhong@hit.edu.cn"這個(gè)郵箱(我的郵箱),你可以把正則表達(dá)式寫成下面這個(gè)樣子:

importrekey =r"afiouwehrfuichuxiuhong@hit.edu.cnaskdjhfiosueh"p1 =r"chuxiuhong@hit\.edu\.cn"pattern1 = re.compile(p1)printpattern1.findall(key)

發(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>

importrekey =r"http://www.nsfbuhwe.com and https://www.auhfisna.com"#胡編亂造的網(wǎng)址,別在意p1 =r"https*://"#看那個(gè)星號(hào)践付!pattern1 = re.compile(p1)printpattern1.findall(key)

輸出

['http://', 'https://']

2.比方說我們有這么一個(gè)字符串"cat hat mat qat"秦士,你會(huì)發(fā)現(xiàn)前面三個(gè)是實(shí)際的單詞,最后那個(gè)是我胡編亂造的(上百度查完是昆士蘭英語學(xué)院的縮寫= =)永高。如果你本來就知道"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

importrekey =r"lalala<hTml>hello</Html>heiheihei"p1 =r"<[Hh][Tt][Mm][Ll]>.+?</[Hh][Tt][Mm][Ll]>"pattern1 = re.compile(p1)printpattern1.findall(key)

輸出

['<hTml>hello</Html>']

我們既然有了范圍性的匹配届吁,自然有范圍性的排除错妖。

[^]代表除了內(nèi)部包含的字符以外都能匹配

還是cat,hat,mat,qat這個(gè)例子,我們想匹配除了qat以外的疚沐,那么就應(yīng)該這么寫:

importrekey =r"mat cat hat pat"p1 =r"[^p]at"#這代表除了p以外都匹配pattern1 = re.compile(p1)printpattern1.findall(key)

輸出

為了方便我們寫簡潔的正則表達(dá)式暂氯,它本身還提供下面這樣的寫法

正則表達(dá)式代表的匹配字符

[0-9]0123456789任意之一

[a-z]小寫字母任意之一

[A-Z]大寫字母任意之一

\d等同于[0-9]

\D等同于[^0-9]匹配非數(shù)字

\w等同于[a-z0-9A-Z_]匹配大小寫字母、數(shù)字和下劃線

\W等同于[^a-z0-9A-Z_]等同于上一條取非

3.介紹到這里亮蛔,我們可能已經(jīng)掌握了大致的正則表達(dá)式的構(gòu)造方式痴施,但是我們常常會(huì)在實(shí)戰(zhàn)中遇到一些匹配的不準(zhǔn)確的問題。比方說:

importrekey =r"chuxiuhong@hit.edu.cn"p1 =r"@.+\."#我想匹配到@后面一直到“.”之間的究流,在這里是hitpattern1 = re.compile(p1)printpattern1.findall(key)

輸出結(jié)果

['@hit.edu.']

呦呵辣吃!你咋能多了呢?我理想的結(jié)果是@hit.芬探,你咋還給我加量了呢神得?這是因?yàn)檎齽t表達(dá)式默認(rèn)是“貪婪”的,我們之前講過偷仿,“+”代表是字符重復(fù)一次或多次哩簿。但是我們沒有細(xì)說這個(gè)多次到底是多少次。所以它會(huì)盡可能“貪婪”地多給我們匹配字符酝静,在這個(gè)例子里也就是匹配到最后一個(gè)“.”节榜。

我們?cè)趺唇鉀Q這種問題呢?只要在“+”后面加一個(gè)“形入?”就好了全跨。

importrekey =r"chuxiuhong@hit.edu.cn"p1 =r"@.+?\."#我想匹配到@后面一直到“.”之間的缝左,在這里是hitpattern1 = re.compile(p1)printpattern1.findall(key)

輸出結(jié)果

['@hit.']

加了一個(gè)“?”我們就將貪婪的“+”改成了懶惰的“+”亿遂。這對(duì)于[abc]+,\w*之類的同樣適用。

小測驗(yàn):上面那個(gè)例子可以不使用懶惰匹配渺杉,想一種方法得到同樣的結(jié)果

**個(gè)人建議:在你使用"+","*"的時(shí)候蛇数,一定先想好到底是用貪婪型還是懶惰型,尤其是當(dāng)你用到范圍較大的項(xiàng)目上時(shí)是越,因?yàn)楹苡锌赡芩投嗥ヅ渥址貋斫o你6恕!!**

為了能夠準(zhǔn)確的控制重復(fù)次數(shù)浦徊,正則表達(dá)式還提供

{a,b}(代表a<=匹配次數(shù)<=b)

還是舉個(gè)栗子馏予,我們有sas,saas,saaas,我們想要sas和saas盔性,我們?cè)趺刺幚砟兀?/p>

importrekey =r"saas and sas and saaas"p1 =r"sa{1,2}s"pattern1 = re.compile(p1)printpattern1.findall(key)

輸出

['saas', 'sas']

如果你省略掉{1,2}中的2霞丧,那么就代表至少匹配一次,那么就等價(jià)于冕香?

如果你省略掉{1,2}中的1蛹尝,那么就代表至多匹配2次。

下面列舉一些正則表達(dá)式里的元字符及其作用

元字符說明

.代表任意字符

|邏輯或操作符

[ ]匹配內(nèi)部的任一字符或子表達(dá)式

[^]對(duì)字符集和取非

-定義一個(gè)區(qū)間

\對(duì)下一字符取非(通常是普通變特殊悉尾,特殊變普通)

*匹配前面的字符或者子表達(dá)式0次或多次

*?惰性匹配上一個(gè)

+匹配前一個(gè)字符或子表達(dá)式一次或多次

+?惰性匹配上一個(gè)

?匹配前一個(gè)字符或子表達(dá)式0次或1次重復(fù)

{n}匹配前一個(gè)字符或子表達(dá)式

{m,n}匹配前一個(gè)字符或子表達(dá)式至少m次至多n次

{n,}匹配前一個(gè)字符或者子表達(dá)式至少n次

{n,}?前一個(gè)的惰性匹配

^匹配字符串的開頭

\A匹配字符串開頭

$匹配字符串結(jié)束

[\b]退格字符

\c匹配一個(gè)控制字符

\d匹配任意數(shù)字

\D匹配數(shù)字以外的字符

\t匹配制表符

\w匹配任意數(shù)字字母下劃線

\W不匹配數(shù)字字母下劃線


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末突那,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子构眯,更是在濱河造成了極大的恐慌愕难,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惫霸,死亡現(xiàn)場離奇詭異务漩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)它褪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門饵骨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人茫打,你說我怎么就攤上這事居触。” “怎么了老赤?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵轮洋,是天一觀的道長。 經(jīng)常有香客問我抬旺,道長弊予,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任开财,我火速辦了婚禮汉柒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘责鳍。我一直安慰自己碾褂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布历葛。 她就那樣靜靜地躺著正塌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乓诽,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天帜羊,我揣著相機(jī)與錄音,去河邊找鬼鸠天。 笑死逮壁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粮宛。 我是一名探鬼主播窥淆,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼巍杈!你這毒婦竟也來了忧饭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤筷畦,失蹤者是張志新(化名)和其女友劉穎词裤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳖宾,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吼砂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鼎文。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渔肩。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拇惋,靈堂內(nèi)的尸體忽然破棺而出周偎,到底是詐尸還是另有隱情,我是刑警寧澤撑帖,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布蓉坎,位于F島的核電站,受9級(jí)特大地震影響胡嘿,放射性物質(zhì)發(fā)生泄漏蛉艾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一衷敌、第九天 我趴在偏房一處隱蔽的房頂上張望勿侯。 院中可真熱鬧,春花似錦逢享、人聲如沸罐监。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春侧但,著一層夾襖步出監(jiān)牢的瞬間矢空,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工禀横, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屁药,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓柏锄,卻偏偏與公主長得像酿箭,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趾娃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 金融民工的飯局裝逼指南缭嫡!說的是你嗎? 話說抬闷,金融圈飯局龍佛混雜妇蛀,局中的金融人壕裝難辨。 國慶節(jié)馬上就要到了笤成,金融圈...
    feng147閱讀 177評(píng)論 0 0
  • 真正靠譜的人评架,都有這3種能力 一個(gè)人之所以靠譜,往往是因?yàn)?種能力: 高效的閉環(huán)溝通能力炕泳、有坑必填的執(zhí)行能力纵诞、抗打...
    飛軒皓閱讀 168評(píng)論 0 0
  • 兩種重要的系統(tǒng)函數(shù)1、全通系統(tǒng)系統(tǒng)的零點(diǎn)和極點(diǎn)關(guān)于虛軸對(duì)稱分布的系統(tǒng)稱為全系統(tǒng)系統(tǒng)對(duì)所有的頻率分量都有相同的增益一...
    快樂的大腳aaa閱讀 1,405評(píng)論 0 0
  • 今天得知一位同事的爸爸在昨天去世了培遵,我專門找到她的朋友圈挣磨,去她昨天發(fā)的圈下面跟了一個(gè)問候』缍看著她痛徹心扉的只言片語...
    談天1995閱讀 178評(píng)論 0 0
  • 先祝自己22歲生日快樂。 最近不順心的事情接踵而至廊宪,著實(shí)讓我崩潰矾瘾,比起這些逆境,更讓我感到無助的是對(duì)于未來的迷茫箭启。...
    動(dòng)力妹閱讀 342評(píng)論 0 0