python3中的正则模块
本文引至: 正則模塊
與正則最相關的應該算是字符串, 但是,在內置的py的str類型中, 并沒有內置的正則方法. 我們可以看一下str的基本方法:
我覺得最有用的,應該算find,len,split,join 這4個方法了. 但對于字符串操作來說, 這簡直too too simple. 所以, py提供了我們一個Re 模塊, 來幫助我們使用正則對字符串進行相關操作. 另外, py中的正則是perl-like 所以, 支持的正則的特性比js多很多.
使用Re
首先, 我們需要導入正則模塊.
import re我們可以使用dir(re) 來查看里面主要有哪些方法. 或者你可以直接查閱python官網. 這樣, 我們就可以使用相關的正則方法了.
在正式使用方法之前, 我們得學習一下, 如果在py中寫正則. 因為py不同于其他語言使用// (slashes) 作為正則標識符, py使用r 作為正則表達式的flag.
接下來, 我們會邊介紹re模塊的同時, 簡單說明一下,python的正則語法.
match
match 用來找到string中被pattern 匹配的部分.
基本的syntax:
re.match(pattern, string, flags=0)
pattern: 正則表達式
string: 被匹配的字符串
flags: 用來表示正則匹配的模式, 比如忽略大小寫, 全局匹配等
match 返回的是 re 自定義的match object. 當然, 如果沒有匹配到的話, 則會返回None. 我們看個demo:
reg = re.match(r"\w", "wa"); # 加上flag: re.I -> 忽略大小寫 reg = re.match(r"\w", "wa",re.I);如果匹配到了, 我們該怎么從里面獲得我們想要的呢?
很簡單: match object 上面自帶了兩個方法: group和groups
group(num=0): 用來返回匹配到的內容,0返回的是全部匹配到的內容. 從1開始是返回通過(...)匹配到的內容
groups() : 返回所有通過(...)匹配到的子內容, 并且放在tuple 當中.
還有一個常用的方法是search. 目前并不知道, 他和match的區別在哪里.
search
search 方法用來查找第一個正則匹配到的str內容. 同樣,如果匹配到,他也會返回match Object. 如果沒有匹配到, 則會返回None. 所以, 他的match上的方法和上面是一樣的
不過, 實際上兩者還是有區別的。 根據官方的介紹, match 只能從string的開頭部分開始匹配, 而search則可以從任何一個位置開始匹配. 相當于:
match 默認就是r"^xxxx" 醬汁.
search則和javascript中的/\w+/g 全局匹配類似.
具體看一個demo吧:
search = re.search(r"123", "aresmarter12323handogs"); match = re.match(r"123", "aresmarter12323handogs") print(search.group()) # Cats are print(match.group()) # AttributeError使用match來說, 這一點就比較尷尬了.
sub
該方法是將匹配到的str 部分使用 指定字符串替代. 實際上, 和python的replace方法一樣. 只是他是使用正則進行匹配的:
syntax:
re.sub(pattern, repl, string, max=0)
pattern: 正則表達式
repl: 就是replace 用來替代的字符串
string: 目標字符串
max: 替換次數.為0 則默認不替換, 為1則表示替換一處
看示例吧, 清楚一點
reg = re.sub(r"\d+","", "remove digital from xxx123xxx123xx"); print(reg) # remove digital from xxxxxxxxreg = re.sub(r"\d+","", "remove digital from xxx123xxx123xx",1); print(reg) # remove digital from xxxxxx123xxcompile
這是python提供的一個parse regexp 的方法函數. 實際上, 是為了更好的復用正則. 比如, 我有一處正則, 但是,我想多次用的話, 在沒有compile的情況下, 就只能copy了. 這實際上和javascript中的 RegExp 對象是一個道理. 并且, 該方法上掛載了,所有依賴正則的方法, 也就是說, 需要輸入pattern的地方,都可以直接使用dot來調用.
基本格式為:
re.compile(pattern, flags=0)
看個demo吧:
getDigital = re.compile(r'\d+',re.I) a_str = 'remove digital from xxxxxx123xx' removeDigital = getDigital.sub('',a_str) print(removeDigital) # remove digital from xxxxxxxx看情況用吧
findall
從上面的match和search開始,我就覺得很有必要吧findall 提出來, 因為, 該方法比match和search來說更常見. 按照使用頻率我們可以排序:
findall > search > match
findall的作用就是, 全局匹配.
格式為:
re.findall(pattern, string, flags=0)
他返回的內容并不是match object, 而是一個list, 用來表示在整個string中, 被pattern 匹配到的內容.
(和match差不了多少)
看一下demo:
fullmatch
fullmatch 用來表示正則和string是完全匹配的關系. 相當于從頭到尾, 如果匹配到, 這返回相關內容, 否則返回None. fullmatch 相當于 r"\A your regular expression \Z". (你也可以使用^替代 \A, $ 替代\Z)
格式為:
fullmatch(pattern, string, flags=0)
看個demo:
get_digital = re.fullmatch(r'\d{3,11}',"331213322") same_effect = re.match(r'^\d{3,11}$',"331213322") print(get_digital.group()) # 使用fullmatch print(same_effect.group()) # 使用\A \Z 進行匹配split
和str中的split方法比起來, 他的作用就是多出一個正則匹配. 返回的是list.
格式為:
split(pattern, string, maxsplit=0, flags=0)
看個demo吧:
split_str = re.split(r'\d','this is 1 this is 2') print(split_str) # ['this is ', ' this is ', '']最后再介紹一個escape 方法. 常常用在處理惡意字符當中.
escape
用來過濾其他字符, 只會保留ASCII和數字(在v3.3版本之前 支持_, 不過現在不支持了). 他的返回值就是一個新的str.
格式為:
escape(string)
看個demo:
esc = re.escape('I"m a evil <script> window.location.href="villainhr.com"</script>') print(esc) # 最后得到的內容全部使用\ 進行轉義. # I\"m\ a\ evil\ \<script\>\ window\.location\.href\=\"villainhr\.com\"\<\/script\>介紹完了基本的方法, 我們來深入的看看, match object上面到底存在些什么方法和屬性.
Match Object
match object是 match 和 search 返回的結果. 上文介紹了, MO(match object) 中存在的兩個基本方法, group() 以及 groups(). 參考官方文檔, 我們可以了解到, MO還存在其他一些很有用的方法。
start([group]): 找到某個group 在str中開始的位置. 返回的是Number。
end([group]): 和start 一樣, 返回某個group的結束位置.
官方提供了幾種使用start和end快速獲取匹配內容的辦法.
匹配第二個分組之前的內容:(記住,第二個分組就是index為2,index為1是所有匹配到的內容)
匹配第二個分組到第一個分組之間的內容:
其他的, 到具體業務場景再說吧.
span([group]): 返回指定group 在原來str中占的范圍.
lastindex: 返回最后一個分組的index. 如果沒有匹配到分組, 則返回None. lastindex 實際上可以用來表示匹配到分組的長度(記得 +1 就行了)
lastgroup: 返回最后一個分組的命名. 這估計就要牽扯到,正則的命名了. 我們來看一個簡單的demo:
在python中, 我們可以使用(?P< xxx>)的格式進行命名. 實際上, lastgroup用到的并不多, 可以說非常少.
基本上, 關于re的方法,以及MO的方法和屬性都已經介紹完畢了.
接下來我們補充一下,關于flags 和 分組的使用(結合group)
regexp supplement
分組的作用
上文說到了分組表示, 但是還沒有深入說一下, 相關分組到底有什么x用. 使用分組簡單的說來有兩個好處,一個是sub方法, 一個是group 方法.
這里, 我們先說一下 group方法吧.
我們可以使用\number這樣的默認分組,也可以使用 直接定義命名(?P<xxx>)。 如果使用前者, 那么我們的group方法, 可以說根本發揮不了什么效果.
Old style:
由于分組是從1開始, 所以,我們這里也就理解了, 為什么group(0) 不算分組而算全部匹配的內容.
我們使用命名的方式,使用group來獲取一下.
New style:
如果使用這樣的方式來的話, 語義清晰, 方便快捷. 五星推薦.
分組還有另外一個好處,就是使用sub方法, 能夠快速實現HTML替換.
直接看demo吧:
當然, 你也可以直接使用命名的方法:
exa = '<text top="33" font="0"><b>test</b></text>' new_text = re.sub(r"<b>(?P<innerHTML>.*?)</b>", r'\g<innerHTML>',exa); print(new_text)這就是分組的作用.
另外, 我們還得需要看看 re提供的幾個正則flag
flag
這里就列幾個比較常用的吧:
| re.I | 忽略大小寫匹配 |
| re.M | 多行匹配. 通常情況下,^和$ 會從str的開頭限定到結果,如果是多行的話也是這樣. 使用了re.M的flag之后, 就可以設定, 在str的每一行都使用^...$里面的內容進行匹配 |
| re.S | 該flag是正針對于.而設置的. 因為.是可以匹配任意字符,但不包括換行符. 但,如果你加上這個flag后, 那么.就可以匹配所有字符 |
| re.X | 相當于一種寬松型regexp. 這種方式的意圖是告訴你,可以使用一種comment 的方式,來寫正則,讓你更寬的理解他. 并且,regexp中的空格全部無效,除非你顯示使用\s |
根據官網提供的demo,我們來解釋一下re.X的作用.
a = re.compile(r"""\d + # the integral part\. # the decimal point\d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*") # a 等價于b看demo, 我覺得就已經足夠了.
關于正則的基本內容就到這里, 我們最后來看看總結吧.
總結
以上是生活随笔為你收集整理的python3中的正则模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到路边躺着好几个死人
- 下一篇: 梦到螃蟹腿是什么意思