02:正则表达式
正則表達式(regular expression)主要功能是從字符串(string)中通過特定的模式(pattern),搜索想要找到的內(nèi)容。
正則表達式的匹配過程是:依次拿出表達式和文本中的字符比較,如果每一個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。
?
一、正則基礎(chǔ)
1、元字符
| 字符 | 描述 |
| . | 匹配出換行符以外的任意字符 |
| \w | 匹配字母數(shù)字或下劃線或者漢字或者下劃線 |
| \s | 匹配任意空白符相當(dāng)于[ \r\n\f\t\v] |
| \d | 匹配數(shù)字 |
| \b | 匹配單詞邊界,它只是匹配一個位置(不匹配字符) |
| ^ | 匹配字符串開始(在多行模式中,匹配每一行開始) |
| $ | 匹配字符串結(jié)束(在多行模式中匹配沒一行結(jié)束) |
Tips:\b 是一個特殊代碼,代表著單詞的開頭或結(jié)尾,也就是單詞的分界處。雖然通常英文的單詞是由空格,標(biāo)點符號或者換行來分隔的,但是 \b 并不匹配這些單詞分隔字符中的任何一個,它只匹配一個位置。更精確的說法,\b 匹配這樣的位置:它的前一個字符和后一個字符不全是(一個是,一個不是或不存在) \w。
Tips:\b在字符組外表示單詞邊界,但是在字符組內(nèi)表示退格。\B表示非單詞邊界。
#匹配位置,新增字符import re sre = r'(?<=\d)(?=(?:\d{3})+\b)' msg = 'there are 21931284028392 people' re.sub(sre,',',msg) #'there are 21,931,284,028,392 people'
#去掉指定關(guān)鍵前后的額外部分
msg1 = 'The cats is a dogor'
sre1 = r'(?<=\b(?:cat|dog))\w+(?=\b)'
re.sub(sre1,'',msg1) #'The cat is a dog'
#把所有16進制轉(zhuǎn)成0xNN形式
msg3 = '0x5 0xf3'
sre3 = r'(?<=0x)(?=[1-9a-zA-Z]\b)'
re.sub(sre3, '0', msg3) #0x05 0xf3
#分割多種格式的字符串
line = 'asdf fjdk; afed, fjek,asdf, foo'
re.split(r'[;,\s]\s*', line) #['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
#當(dāng)你使用?re.split()?函數(shù)時候,需要特別注意的是正則表達式中是否包含一個括號捕獲分組。 如果使用了捕獲分組,那么被匹配的文本也將出現(xiàn)在結(jié)果列表中
fields = re.split(r'(;|,|\s)\s*', line) #['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
#如果你不想保留分割字符串到結(jié)果列表中去,但仍然需要使用到括號來分組正則表達式的話, 確保你的分組是非捕獲分組,形如?(?:...)
fields = re.split(r'(?:,|;|\s)\s*', line) #['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']#匹配但是不捕獲
?
例如: It's very nice.
'I' 占一個位置,'t' 占一個位置,所有的單個字符都會占一個位置,這樣的位置我給它取個名字叫“顯式位置”。
注意:字符與字符之間還有一個位置,例如 'I' 和 't' 之間就有一個位置(沒有任何東西),這樣的位置我給它取個名字叫“隱式位置”。
?
“隱式位置”就是 \b 的關(guān)鍵!通俗的理解,\b 就是“隱式位置”。
\bnice\b 這里就能匹配出 "nice" 這個單詞
?
反義字符
?
| 代碼/語法 | 說明 |
| \W | 匹配任意一個不是字母或數(shù)字下劃線或漢字的字符 |
| \S | 匹配任意一個不是空白符的字符 |
| \D | 匹配不是數(shù)字的字符 [^\d] |
| \B | 匹配不是單詞開頭或者結(jié)尾的位置 |
| \A | 僅匹配開頭 |
| \Z | 僅匹配末尾 |
| [^X] | 匹配除了X以外的任意字符 |
| [^aeiou] | 匹配除了aeiou這幾個字母以外的任意字符 |
?
?
2、轉(zhuǎn)移字符
如果你想要得到元字符本身的話需要使用“\”來取消這些元字符的特殊意義
3、字符類
[]能夠匹配所包含的一系列字符中的任意一個。需要注意的是,[]雖然能匹配其中的任意一個字符,但匹配的結(jié)果只能是一個字符,不是多個。
[\u4e00-\u9fa5]表示任意一個漢字
?
?
[^ ] 排除型字符組,[]本身表示的就是字符之間“或”的關(guān)系,因此在[]中使用“|”來表示“或”的關(guān)系是錯誤的。
?
3、重復(fù)
?
| 表達式 | 說明 | 舉例 |
| {m} | 表達式匹配m次 | “\d{3}”相當(dāng)于“\d\d\d ” “(abc){2}”相當(dāng)于“abcabc” |
| {m,n} | 表達式匹配最少m次,最多n次 | “\d{2,3}”可以匹配“12”或“321”等2到3位的數(shù)字 |
| {m,} | 表達式至少匹配m次 | “[a-z]{8,}”表示至少8位以上的字母 |
| ? | 表達式匹配0次或1次,相當(dāng)于{0,1} | “ab?”可以匹配“a”或“ab” |
| * | 表達式匹配0次或任意多次,相當(dāng)于{0,} | “<[^>]*>”中“[^>]*”表示0個或任意多個不是“>”的字符 |
| + | 表達式匹配1次或意多次,至少1次,相當(dāng)于{1,} | “\d\s+\d”表示兩個數(shù)字中間,至少有一個以上的空白字符 |
?
4、分支結(jié)構(gòu)
?
當(dāng)一個字符串的某一子串具有多種可能時,采用分支結(jié)構(gòu)來匹配,“|”表示多個子表達式之間“或”的關(guān)系,“|”是以()限定范圍的,如果在“|”的左右兩側(cè)沒有()來限定范圍,那么它的作用范圍即為“|”左右兩側(cè)整體。(正則表達式是從左到右依次匹配,如果滿足了某個分支的話它就不會再管其他分支了)
?
?
二、正則進階
1、捕獲組
捕獲組就是把正則表達式中子表達式匹配的內(nèi)容,保存到內(nèi)存中以數(shù)字編號或手動命名的組里,以供后面引用。
?
| 表達式 | 說明 |
| (Expression) | 普通捕獲,將子表達式Expression匹配的內(nèi)容保存到以數(shù)字編號的組里 |
| (?<name> Expression) | 命名捕獲,將子表達式Expression匹配的內(nèi)容保存到以name命名的組里 |
?Tips:在.NET中使用(?’name’Expression)與使用(?<name>Expression)是等價的。在PHP和Python中命名捕獲組語法為:(?P<name>Expression)
?
普通捕獲:實際上組號分配過程是要從左向右掃描兩遍的:第一遍只給未命名組分配,第二遍只給命名組分配。未命名編號是按“(”出現(xiàn)的順序,從左到右,從1開始進行編號的 。(\d{1,3}){3}\d{3}:這個正則表達式的意思就是把我們分組的小括號里面的東西重復(fù)三次.group(2)---->valueError
?
命名捕獲:通過捕獲組名,而不是序號對捕獲內(nèi)容進行引用,提供了更便捷的引用方式,不用關(guān)注捕獲組的序號,也不用擔(dān)心表達式部分變更會導(dǎo)致引用錯誤的捕獲組。
2、非捕獲組
一些表達式中,不得不使用( ),但又不需要保存( )中子表達式匹配的內(nèi)容,這時可以用非捕獲組來抵消使用( )帶來的副作用。
| 表達式 | 說明 |
| (?:Expression) | 剝奪一個分組對組號分配的參與權(quán) |
?
3、對捕獲組的引用:
?
1)?????? 正則表達式中,對前面捕獲組捕獲的內(nèi)容進行引用,稱為反向引用;
反向引用則用于重復(fù)搜索前面某個分組匹配的文本,例如\1代表分組1匹配的文本
| 表達式 | 說明 |
| \k(number)簡寫\1,\2 | 對序號為1和2的捕獲組的反向引用 |
| \k<name> | 對命名為name的捕獲組的反向引用 |
?
2)?????? 正則表達式中,(?(name)yes|no)的條件判斷結(jié)構(gòu);
(?(?=a)\w{2}|\w) :當(dāng)前位置右側(cè)如果是字符“a” ,則匹配兩個“\w”,否則匹配一個“\w”。
3)?????? 在程序中,對捕獲組捕獲內(nèi)容的引用。
?
4、零寬斷言和負零寬斷言
Tips:(如果子表達式匹配的僅僅是位置,或者匹配的內(nèi)容并不保存到最終的匹配結(jié)果中,那么就認為這個子表達式是零寬度的。)
?
| 分類 | 代表/語法 | 說明 |
| ? ? 捕獲 ? ? | (exp) | 匹配exp,并捕獲文本到自動命名的組里 |
| (?<name>exp) | 匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?’name’exp) | |
| (?:exp) | 匹配exp,不捕獲匹配文本,也不給分組分配組號 | |
| ? ? ?斷言 ? ? ? | (?=exp) | 匹配exp前面位置,但是不匹配exp(順序肯定環(huán)視) |
| (?<exp) | 匹配exp后面位置,但是不匹配exp(逆序肯定環(huán)視) | |
| (?!exp) | 匹配后面的不是exp的位置,但是不匹配exp(順序否定環(huán)視) | |
| (?<!exp) | 匹配前面不是exp的位置,但是不匹配exp(逆序否定環(huán)視) | |
| 注釋 | (?#comment) | 注釋 |
?
零寬度斷言
?
1.(?=exp):也叫零寬度正預(yù)測先行斷言,表示所在位置右側(cè)能夠匹配exp
?
例如:\b\w+(?=ing\b)則這個正則表達式 就是匹配一ing結(jié)尾的單詞,但是不包含ing,這個零寬度正預(yù)測先行斷言可以這樣理解,我們就以上面的正則表達式作為例來進行講解,首先我們肯定是匹配 源文本為doing它會先匹配d的時候它會瞻仰一下后面跟的是不是ing,如果不是就會繼續(xù)往下走,匹配到第二個字符o它會預(yù)測(或瞻仰)下后面是不是 ing如果是整個表達式就結(jié)束了,并且不匹配ing。而這個可以總結(jié)一句話就是匹配exp前面的東西
?
2.(?<=exp):也叫零寬度正回顧斷言, 表示所在位置左側(cè)能夠匹配exp,這句話聽著很繞口,其實零寬度正回顧斷言中解釋說是自身出現(xiàn)位置這個自身出現(xiàn)位置是表示它匹配的文本,就比如 說(?<=Ding)\d{3}這個正則表達式,這里的自身出現(xiàn)的位置僅僅是從開始匹配文本的時候也就是\d{3}也就是主動權(quán)在這個\d{3}的 時候才是自身匹配的位置。舉例說明源文本,比如匹配Din123,按照我們的常理理解的是數(shù)字123是自身匹配的位置,但是前面不是Ding所以匹配不成 功,我們可以講這個表達式理解為就是以exp為開始的正則表達式但是不包含exp,意思就是匹配exp后面的東西。
?
負向零寬斷言:(可以和上面的進行對比來學(xué)哦!這個表達式的是否定的)
?
1.(?!exp):也叫零寬度負預(yù)測先行斷言,表示所在位置右側(cè)不能夠匹配exp
?
例如:\d{3}(?!123):正則表達式的含義表達了前面匹配的是三個數(shù)字,匹配的位置就是當(dāng)前匹配的這三個數(shù)字后面跟的不能是123。
?
2.(?<!exp):零寬度負回顧斷言,表示所在位置左側(cè)不能匹配exp。
?
5:正則引擎:
DFA(確定型有窮自動機)和NFA(非確定型有窮自動機),而NFA又可以分為傳統(tǒng)型NFA和POSIX NFA。
DFA引擎不需要回溯,匹配快速。不能匹配具有反向引用的模式,還不可以捕獲子表達式
正則的匹配過程,通常情況下都是由一個子表達式(可能為一個普通字符、元字符或元字符序列組成)取得控制權(quán),從字符串的某一位置開始嘗試匹配,一個子表達式開始嘗試匹配的位置,是從前一子表達匹配成功的結(jié)束位置開始的。
?
6.匹配的貪婪與非貪婪模式
標(biāo)準(zhǔn)量詞修飾的子表達式,在可匹配可不匹配的情況下,總會先嘗試進行匹配,稱這種方式為匹配優(yōu)先,或者貪婪模式。“{m}”、“{m,n}”、“{m,}”、“?”、“*”和“+”都是匹配優(yōu)先的。
一些NFA正則引擎支持忽略優(yōu)先量詞,也就是在標(biāo)準(zhǔn)量詞后加一個“?”,在可匹配可不匹配的情況下,總會先忽略匹配,只有在由忽略優(yōu)先量詞修飾的子表達式,必須進行匹配才能使整個表達式匹配成功時,才會進行匹配,稱這種方式為忽略優(yōu)先,或者非貪婪模式。忽略優(yōu)先量詞包括“{m}?”、“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
三: re模塊
re.compile(strPattern[, flag]) #正則編譯
| re.I | re.IGNORECASE | 忽略大小寫 |
| re.M | re.MULTILINE | 多行模式,改變'^'和'$'的行為 |
| re.S | re.DOTALL | 點任意匹配模式(包括換行符),改變'.'的行為 |
| re.L | re.LOCALE | 使預(yù)定字符類 \w \W \b \B \s \S 取決于當(dāng)前區(qū)域設(shè)定 |
| re.U | re.UNICODE | 使預(yù)定字符類 \w \W \b \B \s \S \d \D 取決于unicode定義的字符屬性 |
| re.X | VERBOSE | 詳細模式。這個模式下正則表達式可以是多行,忽略空白字符,并可以加入注釋。 |
Match對象
*屬性
string: 匹配時使用的文本
re: 匹配時使用的Pattern對象。
pos: 文本中正則表達式開始搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數(shù)相同。
endpos: 文本中正則表達式結(jié)束搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數(shù)相同。
lastindex: 最后一個被捕獲的分組在文本中的索引。如果沒有被捕獲的分組,將為None。
lastgroup: 最后一個被捕獲的分組的別名。如果這個分組沒有別名或者沒有被捕獲的分組,將為None
*方法:
res.group([group1, …]) #不填寫參數(shù)時,返回group(0)
res.groups([default]): #所有
start([group]),?end([group]),?span([group]) #返回匹配在string的位置
match()和search() #返回Match對象
split(), findall() #返回匹配的子串將string分割后返回列表
finditer() #搜索string,返回一個順序訪問每一個匹配結(jié)果(Match對象)的迭代器。
re.sub(pattern, repl, string[, count]) #返回使用repl替換string中每一個匹配的子串后返回替換后的字符串。
re.sub(pattern, repl, string[, count]) #返回 (sub(repl, string[, count]), 替換次數(shù))。
轉(zhuǎn)載于:https://www.cnblogs.com/holens/p/5018183.html
總結(jié)
- 上一篇: 如何把关联性的告警智能添加到 Nagio
- 下一篇: android——fragment长时间