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