日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

re:正则表达式,字符串处理的杀手锏

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 re:正则表达式,字符串处理的杀手锏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

正則表達式是一種用形式化語法描述的文本匹配模式,可以進行復雜的字符串匹配。 Python中的正則表達式通過re模塊提供,功能比Python內置的str更強,但是速度沒有str提供的方法快。 因此如果內置的str方法可以解決,那么直接用就可以。如果不好解決,再使用正則。

1.查找文本中的模式

python ''' re最常見的方法就是搜索文本中的模式。match和search函數接收pattern(模式)和text(文本)作為輸入,找到這個模式時,就返回一個Match對象。 如果沒有找到模式,則返回None。 每個Match對象包含有關匹配性質的信息,包括原輸入字符串,所使用的正則表達式,以及模式在原字符串中出現的位置。 ''' pattern = "this" text = "你知道this的含義嗎?" match = re.search(pattern, text) print(match) # <re.Match object; span=(3, 7), match='this'> print(match.start()) # 3 print(match.end()) # 7 print(text[match.start(): match.end()]) # this # 以上是search,那么match呢? match = re.match(pattern, text) print(match) # None # 返回結果為None,match和search比較類似,但match只能從頭匹配查找, 而search可以在字符串的任意位置匹配查找。 # 即使有多個滿足條件的也只會返回第一個。 print(re.search("this", "123this456this789this")) # <re.Match object; span=(3, 7), match='this'> # 如果沒有則返回None,此時調用下面的start或end方法也會報錯。會拋出AttributeError: 'NoneType' object has no attribute 'xxxxxx' # 因此可以加上一層判斷 match = re.match(pattern, text) if match: print(match.start())

2.編譯表達式

python import re''' 我們也可以將模式進行一個編譯,比如我們有很多手機號,但我只查詢以135開頭的。 按照我們剛才講的,可以這么做。 for number in number_list:if re.match("135", number):print(number) 這么做毫無疑問是可行的,但是我們每循環一次,pattern都要編譯一次。既然pattern是固定不變的,我們是不是可以提前將它編譯好呢? 答案是可以的 ''' # 得到編譯之后的對象 comp = re.compile("135") # 下面就可以直接使用這個編譯的對象進行查找就可以了 number_list = ["13541258742", "18845214415", "13512441552"] for number in number_list: # 可以看到,如果使用re的話,需要傳入pattern,但是我們將pattern進行編譯之后,就可以直接調用了。 if comp.match(number): print(number) ''' 13541258742 13512441552 ''' ''' re.match(pattern, text) <==> re.compile(pattern).match(text) ''' # 可以對比字符串,準確的說應該對比成類與對象 s = "abc|abcd|efg" print(s.split("|")) # ['abc', 'abcd', 'efg'] # 也可以使用str這個類來調用,但是不方便,于是我們都使用字符串本身,也就是類str的實例對象 print(str.split(s, "|")) # ['abc', 'abcd', 'efg'] # summary:可以傳入pattern和text作為參數,調用re.match,也可以將pattern編譯之后,用編譯之后的對象調用match方法,此時只需傳入text

3.多重匹配

python import re''' 到目前為止,我們所獲取的都是單個實例。如何將滿足條件的所有文本全部獲取呢? 可以使用findall函數 ''' pattern = "abc" text = "abc|abc|abc|abc" print(re.findall(pattern, text)) # ['abc', 'abc', 'abc', 'abc'] # 可以看到,直接將滿足條件的所有實例全部以列表的形式獲取出來了,并且如果滿足條件的實例只有一個,那么得到的仍是一個列表,只是列表里面只有一個元素 # 除此之外還有一個迭代器模式 res = re.finditer(pattern, text) print(res) # <callable_iterator object at 0x00000000029C4400> for v in res: print(v) ''' <re.Match object; span=(0, 3), match='abc'> <re.Match object; span=(4, 7), match='abc'> <re.Match object; span=(8, 11), match='abc'> <re.Match object; span=(12, 15), match='abc'> ''' # 得到的是一個Match對象

4.模式語法

python import re''' 除了簡單的字面量文本字符串,正則表達式還支持更強大的模式。 ''' # 重復 ''' .:代表除換行符之外的任意字符 *:重復0次或者任意多次 +:重復1次或者任意多次 ?:重復0次或者1次 {m}:出現m次 {m,n}:出現m次到n次,包含m和n,并且注意,逗號兩邊不要有空格 {m,}:省略n,那么表示至少出現m次,最多則沒有限制 因此:* == {0,} + == {1,} ? == {0,1} ''' # b出現一次到三次,注意這里不是ab出現一到三次,*+?{}只會作用于它的前一個字符 print(re.search("ab{1,3}", "abcabbc")) # <re.Match object; span=(0, 2), match='ab'> print(re.search("ab{2,3}", "abcabbc")) # <re.Match object; span=(3, 6), match='abb'> ''' 可以看到都是從頭開始找,開頭是ab滿足"ab{1,3}",即使后面有abb也不會匹配了 而"ab{2,3}"則要求b至少出現兩次,因此找到了后面的abb ''' # 可以看到,要求是一到三次,ab,abb,abbb都符合,最終是取了abbb。 # 正則的模式則是貪婪模式,能往多了匹配就往多了匹配 print(re.search("ab{1,3}", "abbbbb")) # <re.Match object; span=(0, 4), match='abbb'> # *+?這些元字符也是同樣的道理 print(re.search("ab*", "abbbbb")) # <re.Match object; span=(0, 6), match='abbbbb'> print(re.search("ab+", "abbbbb")) # <re.Match object; span=(0, 6), match='abbbbb'> print(re.search("ab?", "abbbbb")) # <re.Match object; span=(0, 2), match='ab'> # 那么如何不使用這種貪婪模式呢?可以直接在*+?{}后面加上?即可,表示關閉貪婪模式 # 出現一到三次,關閉貪婪,只獲取一個b print(re.search("ab{1,3}?", "abbbbb")) # <re.Match object; span=(0, 2), match='ab'> # *出現0次或多次,關閉貪婪模式,獲取0次 print(re.search("ab*?", "abbbbb")) # <re.Match object; span=(0, 1), match='a'> # 顯然獲取一次 print(re.search("ab+?", "abbbbb")) # <re.Match object; span=(0, 2), match='ab'> # 出現0次或一次,關閉貪婪模式后顯然獲取0次 print(re.search("ab??", "abbbbb")) # <re.Match object; span=(0, 1), match='a'> # .表示除了換行符的任意字符 print(re.search(".{1,5}", "aaaaa")) # <re.Match object; span=(0, 5), match='aaaaa'> print(re.search(".{1,5}", "aa\naa")) # <re.Match object; span=(0, 2), match='aa'> # 字符集 ''' 下面問題又來了,如果我想獲取以a開頭以c結尾,中間的一個字符必須是love中的一個,想獲取這樣的字符該怎么辦呢? 首先兩端好解決,關鍵是中間的字符要怎么表示? 這個時候字符集就派上用場呢? [love]:用中括號把多個字符組合起來即可,表示匹配l、o、v、e四個字符中的一個 ''' print(re.findall("a[love]c", "awc|aec|afc|akc|adc")) # ['aec'] # 字符集[love]就可以看做是一個整體,也可以搭配元字符使用 ''' [love]{1,3} 表示匹配出現一到三次的字符,什么的字符呢?l、o、v、e四個字符當中的某一個字符 ''' # v在[love]當中,匹配vvv print(re.findall("[love]{1,3}", "vvv")) # ['vvv'] # k不在但是v在,匹配vv print(re.findall("[love]{1,3}", "kvv")) # ['vv'] # 匹配v print(re.findall("[love]{1,3}", "kv")) # ['v'] # a不在,但ve在,匹配ve print(re.findall("[love]{1,3}", "ave")) # ['ve'] # findall是查找所有,l在[love]里面,o在,v在,但是最多出現三次匹配成功結束。繼續查找,最后的e也在,但是_不在,所以匹配結束,得到e。 # y不在,但是o在,u又不在,所以又匹配出e。因此最終結果是['lov', 'e', 'o']。 print(re.findall("[love]{1,3}", "love_you")) # ['lov', 'e', 'o'] # 那我如果想取反呢?也就是我要不在love里面的字符。可以使用[^love],表示非l、o、v、e的任意字符 # 這便是字符集,但是又有一個問題。如果我想獲取為小寫字母的字符呢?難道把26的字母都寫一遍嗎?當然不用 # [a-z]表示所有的小寫字母 # [A-Z]表示所有的大寫字母 # [0-9]表示所有的數字 # [a-zA-Z0-9]表示所有的字母和數字 print(re.findall("[a-z][A-Z]", "aB|ac")) # ['aB'] print(re.findall("[a-zA-Z]", "a|C|4|尻")) # ['a', 'C'] print(re.findall("[a-zA-Z0-9]", "a|C|4|尻")) # ['a', 'C', '4'] # 轉義碼 # \d表示數字 # \D表示非數字 # \w表示字母、數字,注意:這里包括中文 # \W表示非字母數字 # \s表示空白符(制表符、空格、換行等) # \S表示非空白符 # 但是\在操作系統中會先做一層轉義,因此需要兩個\。在操作系統層面上,兩個\變成一個\,然后再和d組合成\d進行正則比配 print(re.search("\\d{1,3}", "1234")) # <re.Match object; span=(0, 3), match='123'> # 那如果我想匹配\呢? print(re.search("\\\\hello", "\\hello")) # <re.Match object; span=(0, 6), match='\\hello'> ''' 要知道\在正則中也是有含義的,因此要匹配純反斜杠,也需要做一次轉義。 所以需要四個\,首先在在操作系統層面會轉義,將四個\變成兩個\,在正則中兩個\變成一個\,此時的\便是普通的字符 但是這樣會很麻煩,因此可以在字符串的開頭加上一個r,表示這是原生的字符串,你不需要給我做任何的轉義 ''' # 此時只需要一個反斜杠即可,可以看到Python中的\w是包含中文的 print(re.search(r"\w{1,2}", "古明地覺")) # <re.Match object; span=(0, 2), match='古明'> # 錨定 ''' 有時除了匹配模式的內容外,我們還要對內容的位置進行一個限制。 ^:這個符號我們剛才好像見過,[^seq],表示不在seq里面的字符,但是如果放在開頭的位置,則表示以某字符開頭,如^abc則表示以abc開頭的字符 $:表示以某字符結尾。如abc$表示以abc結尾的字符 \b:單詞開頭或末尾的空串 \B:不在單詞開頭或末尾的空串 ''' print(re.search(r"^abc", "abcd")) # <re.Match object; span=(0, 3), match='abc'> print(re.search(r"^abc", "aabcd")) # None print(re.search(r"abc$", "dabc")) # <re.Match object; span=(1, 4), match='abc'> print(re.search(r"abc$", "abcd")) # None

5.限制搜索

python import re''' 已經編譯的正則表達式,還可以指定查找的范圍 ''' pattern = re.compile(r"123") text = "123|123|123" print(pattern.search(text, pos=2, endpos=7)) # <re.Match object; span=(4, 7), match='123'> # 指定從2開始,7結束

6.用組解析匹配

python import re''' 有時我們想要提取某些內容中間的內容,比如xxxabcxxx,我想要夾在xxx和xxx之間的內容怎么辦呢? 這個時候就可以用到分組 ''' # 有兩個abc,但我要的是夾在xxx和xxx之間的abc match = re.search(r"xxx(abc)xxx", "abcxxxabcxxx") print(match) # <re.Match object; span=(3, 12), match='xxxabcxxx'> # 這樣匹配依舊會匹配全局,怎么樣才能把括號里面的內容給抽取出來呢? print(match.group(0)) # xxxabcxxx print(match.group(1)) # abc ''' 可以使用group函數,參數默認是0,表示全局。 參數為1,表示第一個括號里面的內容,參數為n,表示第n個括號里面的內容 ''' match = re.search(r"123(.+?)456(.+?)789", "123abc456def789") print(match.group(0)) # 123abc456def789 print(match.group(1)) # abc print(match.group(2)) # def # 那么問題來了,如果是這樣呢? match = re.search(r"123((.+?)456(.+?))789", "123abc456def789") print(match.group(0)) # 123abc456def789 print(match.group(1)) # abc456def print(match.group(2)) # abc print(match.group(3)) # def ''' 可以看到,我在(.+?)456(.+?)外層又加上了一層括號 分組的順序,是從左往右,找到了(,就會進行分組,至于),會自動進行匹配,所以group(1)是最外層的abc456def group(2)是456左邊的(.+?),group(3)是456右邊的(.+?) ''' # 此外還可以給組進行命名。只需要在括號里面加上?P<name>即可,name是我們指定的分組的名字 match = re.search(r"123(?P<yoyoyo>.+?)456(?P<哈哈哈>.+?)789", "123納尼456我屮艸芔茻789") print(match.group("yoyoyo"), match.group("哈哈哈")) # 納尼 我屮艸芔茻 print(match.group(1), match.group(2)) # 納尼 我屮艸芔茻 # 并且使用組的序號依舊是可以的 # 除了group之外,還可以使用groupdict和groups match = re.search(r"123(?P<yoyoyo>.+?)456(?P<哈哈哈>.+?)789", "123納尼456我屮艸芔茻789") print(match.groups()) # ('納尼', '我屮艸芔茻') print(match.groupdict()) # {'yoyoyo': '納尼', '哈哈哈': '我屮艸芔茻'} # groups無論是否指定組名,都會獲取到。但是groupdict只會獲取指定組名的分組,比如說: match = re.search(r"123(?P<yoyoyo>.+?)456(.+?)789", "123納尼456我屮艸芔茻789") print(match.groups()) # ('納尼', '我屮艸芔茻') # 可以看到沒有指定組名的就獲取不到了 print(match.groupdict()) # {'yoyoyo': '納尼'} # 此外在分組的時候,還可以指定管道符|,表示或者。比如 # jpg|png表示獲取的是jpg或者png,注意:管道符會作用于兩邊的全部字符,比如: # www.mashiro.jpg|png,則表示的是www.mashiro.jpg或者png # www.mashiro.(jpg|png),此時的管道符只會作用于括號里面兩端的字符,表示www.mashiro.jpg或者www.mashiro.png print(re.search(r"www\.mashiro\.(jpg|png)", "www.mashiro.jpg")) # <re.Match object; span=(0, 15), match='www.mashiro.jpg'> # 注意這里的\.表示轉義,讓.表示普通的. 不是具有匹配字符能力的. # 但是這里又出現問題了,比如說 text = ''' 這里有圖片哦www.1.jpg,有很多格式的哦 www.2.png,想看嗎,還會動哦,www.3.gif 那還等什么呢?www.banana.jpg, 快去吧,那個象征自由的男人在等著你www.象征自由的男人--尻比.png ''' res = re.findall(r"www.+?(jpg|png|gif)", text) print(res) # ['jpg', 'png', 'gif', 'jpg', 'png'] ''' 可以看到findall獲取的自動是分組里面的內容,可我們要的是整體的鏈接啊。怎么辦呢?一種方法是我在外面也加上括號不就行了 ''' res = re.findall(r"(www.+?(jpg|png|gif))", text) print(res) # [('www.1.jpg', 'jpg'), ('www.2.png', 'png'), ('www.3.gif', 'gif'), ('www.banana.jpg', 'jpg'), ('www.象征自由的男人--尻比.png', 'png')] # 可以看到最外層的分組也被我們所捕獲了,多個分組的內容回族和成一個元組。因此可以使用索引獲取鏈接,但這還不是最完美的方法。 # 有什么辦法,讓里面的那個分組失去效果呢?就是說,我給你加上括號只是為了多匹配一些格式罷了,你就不要自作聰明地當做分組來處理了 # 答案是有的,只需要加上?:即可,在括號里面加上?:表示讓分組失去效果,也就是不表示分組 res = re.findall(r"www.+?(?:jpg|png|gif)", text) print(res) # ['www.1.jpg', 'www.2.png', 'www.3.gif', 'www.banana.jpg', 'www.象征自由的男人--尻比.png'] # 可以看到匹配成功,而且此時最外層也不需要再加上括號了,因為里面的分組失去效果了,相當于就沒有分組了,如果沒有分組,那么默認匹配整體。 # 最后插一句,聊一聊www.+?(?:jpg|png|gif),為什么要是.+?呢,如果是.+行不行,比如: print(re.search(r"www.+?jpg", "www.1.jpg我屮艸芔茻www.2.jpg").group()) # www.1.jpg # 我把?去掉,那么等于變成了貪婪模式。 print(re.search(r"www.+jpg", "www.1.jpg我屮艸芔茻www.2.jpg").group()) # www.1.jpg我屮艸芔茻www.2.jpg # 那么會從第一個www開始,匹配到最后一個jpg,因此要注意開啟非貪婪模式

7.搜索選項

python import re''' 選項標志是用來改變匹配引擎處理表達式的方式。 比如說,我們可以看看re.search()的函數原型 def search(pattern, string, flags=0): 這個pattern和string我們都知道,但是最后一個參數flags是什么鬼? 這個flags就是選項標志,也是我們接下來要說的內容 '''# 大小寫無關 ''' 有些時候,我們不想區分大小寫該怎么辦呢?比如說aa和AA我們認為都是合法的。 ''' # 這便是flags的作用,可以用來改變引擎處理表達式的方式 # re.IGNORECASE表示忽略大小寫敏感模式,其中re.IGNORECASE也可以寫成re.I match = re.match(r"aa", "aA", flags=re.IGNORECASE) print(match) # <re.Match object; span=(0, 2), match='aA'> # 多行輸入 ''' 有兩個標志會影響如何完成多行輸入的搜索:MULTILINE和DOTALL。 MULTILINE表示^和*的錨定規則除了應用于整個字符串之外,還對每一行的開頭和結尾起作用。(不常用) DOTALL表示.這個元字符可以匹配換行符,默認情況下,.這個元字符是不能匹配換行符的,但是加上這個參數之后,便可以匹配換行符 注:re.MULTILINE可以寫成re.M,re.DOTALL可以寫成re.S ''' match = re.match(r".+", "aabb\ncc") print(match) # <re.Match object; span=(0, 4), match='aabb'> match = re.match(r".+", "aabb\ncc", flags=re.DOTALL) print(match) # <re.Match object; span=(0, 7), match='aabb\ncc'> # Unicode ''' 默認情況下,正則表達式處理的都是Unicode文本,也就是說\w是可以匹配中文的。 如果我想只匹配ASCII碼呢?可以使用re.ASCII,這樣的話就不會匹配中文了. re.ASCII也可以寫成re.A ''' print(re.match(r"\w+", "love中國")) # <re.Match object; span=(0, 6), match='love中國'> print(re.match(r"\w+", "love中國", flags=re.ASCII)) # <re.Match object; span=(0, 4), match='love'>

8.字符串替換

python import re''' 我們也可以將字符串進行一個替換 ''' text = "when i was young, i'd listen to the radio" # 我要把當中所有的i替換成大寫的I,怎么做呢? # 可以使用re.sub函數,def sub(pattern, repl, string, count=0, flags=0): # 參數:要替換的字符模式 替換成哪些字符 文本 替換的數量(默認為0,表示全部) 匹配模式 print(re.sub(r"i", "I", text)) # when I was young, I'd lIsten to the radIo # 我要把里面的英文全部刪除 text = "古明地覺(komeiji satori)是一個來自于東方地靈殿的女孩,它有一個妹妹,叫古明地戀(komeiji koishi)" # 把\w都替換成空即可,但是注意\w默認是匹配中文(以及日文等等)的,所以要加上flags=re.A,表示只匹配ASCII碼中的字符 print(re.sub(r"\w", "", text, flags=re.A)) # 古明地覺( )是一個來自于東方地靈殿的女孩,它有一個妹妹,叫古明地戀( ) # 不加flags的話,會把中文也剝掉了 print(re.sub(r"\w", "", text)) # ( ),,( ) # 除此之外還有一個函數叫做subn,和sub一樣,但是除了返回替換的內容,還會返回替換的數量 print(re.subn("a", "b", "accaccacc")) # ('bccbccbcc', 3)

9.利用模式拆分

python import re''' 類似于str.split,re也可以使用split函數,而且功能更加強大 ''' text = "abc1def55455ghi6621" # 我要按照數字切割,最終只保留,abc def ghi該怎么做呢? # 直接調用split即可, 此外還可以指定最多分割多少次,不指定默認為全部。這里表示用數字切割 print(re.split(r"\d", text)) # ['abc', 'def', '', '', '', '', 'ghi', '', '', '', ''] # 可以手動去掉空格 no_space = list(filter(lambda x: len(x), re.split(r"\d", text))) print(no_space) # ['abc', 'def', 'ghi']

轉載于:https://www.cnblogs.com/valorchang/p/11395534.html

總結

以上是生活随笔為你收集整理的re:正则表达式,字符串处理的杀手锏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。