Python基礎學習筆記(十)正則表達式(上)

本節知識大綱:


圖片.png

一、正則表達式介紹

正則表達式是什么?正則表達式是一種特殊的字符串模式,用于匹配一組字符串,就好比模具做產品,而正則就是這個模具,定義一種規則去匹配符合規則的字符。
如果我們對字符串有要求,我們就可以通過正則表達式把它表示出來,我們可以用正則表達式去匹配符合規則的字符串;
正則表達式的處理對象是字符串,主要應用正則表達式的操作有:

  • 驗證
  • 查找
  • 替換
1. 正則表達式的匹配流程:
圖片.png
2. 正則表達式的應用流程

match()是用于校驗的函數
案例01
輸入一個三位數,通過正則表達式輸入的是否滿足要求?

import re
input_number = input("請輸入一個三位數:")
match = re.match("^\d{3}$",input_number)
if match is None:
    print("不符合要求")
else:
    print("符合要求")

案例02
判斷輸入的手機號碼是否有效,要求:號碼位數是11位;第一位是數字1;第二位是數字345789;后面是0-9均可

# 步驟一:通過引擎編譯出對象
import re
pattern = re.compile(R"[1][345789]\d{9}")   # 編譯出pattern對象
input_mobile = input("請輸入手機號碼:")
# 步驟二:對輸入的內容進行匹配
# print(pattern.match(input_mobile))
if pattern.match(input_mobile):
    print("輸入的手機號有效!")
else:
    print("輸入的手機號無效!")
3.正則表達式的基本語法
圖片.png

二、預定義字符

如果每次都通過代碼來驗證正則表達式是否正確效率有點低,我們可以通過在線工具來校驗我們的正則表達式是否正確,比如oschina的在線正則表達式測試工具;當然在Windows系統下可以使用RegexBuddy工具進行檢測。
普通字符:字母、數字、下劃線以及沒有特殊意義的符號,都是普通字符。
元字符:這里主要有11個構成正則表達式元字符

.   \   |   ^   $   *   +   ?   []   {}   ()
1. 通配字符

.是一個能匹配除\n以外任何字符的通用匹配符,例如,我們想匹配以a開頭的,后面跟3個任意字符的正則表達式可以這樣寫:

re.match("^a...","avfs")

另外三個連續的通配符可以寫成{3}像這樣:

re.match("^a.{3}","avfs")

這里也可以使用findall()方法,能返回待匹配字符串中所有與正則表達式相匹配的字符串

print(re.findall("a.{3}","avfssssadddadddaef"))  # 把匹配開頭的^去掉了

輸出結果:

['avfs', 'addd', 'addd']
2. 反斜杠

反斜杠加字母有時候在轉義字符和正則表達式中功能沖突,通常的解決辦法是使用r或者R取消轉義。

三、字符集

1. 系統正則表達式字符集
圖片.png

案例:非數字開頭 + 兩個空格 + 數字/字母/下劃線

import re
print(re.match(R"^\D\s{2}\w$","a  _"))
2. 用戶自定義正則表達式字符集

除了使用系統字符集以外,用戶可以自定義字符集

注意:這里一個中括號只能匹配一個字符;
^在中括號外表示一行開始,在中括號里面表示取反、排除的意思

圖片.png

案例:使用自定義字符集,匹配不區分大小寫以a-f開頭,接接著是三個小寫字母,再后面是以偶數結尾

import re
print(re.findall(R"[a-fA-F][a-z]{3}[02468]","bddf42fbas8"))

注意:除了^-以外,如果把其它任何特殊符號放到[]里,那么就自動去掉特殊意義,只表示符號本身的含義,如.[]里只表示.點號的意思,沒有了通配符的功能。

四、正則表達式中量詞

1. 三種量詞符號

圖片.png

案例:
通過正則表達式匹配英文單詞,要求以na開頭,以e來結尾
方法一:使用*

print(re.findall(R"na[a-z]*e","my name is Alice,nae,nattore"))

輸出結果:

['name', 'nae', 'nattore']

使用*號匹配name(重復1次),匹配nae(重復0次),匹配nattore(重復多次)
方法二:使用+

print(re.findall(R"na[a-z]+e","my name is Alice,nae,nattore"))

輸出結果:

['name', 'nattore']

使用+號,只能匹配name(重復1次),匹配nattore(重復多次)
方法三:使用?

print(re.findall(R"na[a-z]?e","my name is Alice,nae,nattore"))

輸出結果:

['name', 'nae']

使用?號,只能name(重復1次)和nae(重復0次)

案例:
判斷身份證號是否有效,
特征一:長度18或者15位
特征二:前17位是數字
特征三:最后一位是數字或者x

print(re.match(r"(\d{14}[0-9x]|\d{17}[0-9x])","34262320001218646x"))
2. 花括號表示重復次數
圖片.png

(1){n}表示重復n次

# 正則表達式匹配以na開頭加上4個小寫字母并以e結尾:
print(re.findall(R"na[a-z]{4}e","my name is Alice,nae,nattore"))

輸出結果:

['nattore']

(2){n,m}表示重復n到m次

# 正則表達式匹配以na開頭加上3-10個小寫字母并以e結尾:
print(re.findall(R"na[a-z]{3,10}e","my name is Alice,naicajoe,nattorirce"))

輸出結果:

['naicajoe', 'nattorirce']

(3){n,}表示重復n次到無限次

# 正則表達式匹配以na開頭加上3個以上的小寫字母并以e為結尾:
print(re.findall(R"na[a-z]{3,}e","my name is Alice,naicajoe,nattorighjrce"))

輸出結果:

['naicajoe', 'nattorighjrce']
3. 貪婪模式和非貪婪模式

(1)貪婪模式
貪婪模式是指在Python在默認情況下量詞會盡可能多的匹配

print(re.findall("\d+","12345678888888abc"))    # 盡量多的匹配
print(re.findall("\d*","12345678888888abc"))
print(re.findall("\d{3,}","12345678888888abc"))
print(re.findall("\d{3,8}","1234567888888888abc"))

輸出結果:

['12345678888888']
['12345678888888', '', '', '', '']
['12345678888888']
['12345678', '88888888']

(2)非貪婪模式
在表達式的結尾加上問號?,會切換成非貪婪模式

print(re.findall("\d+?","12345678888888abc"))
print(re.findall("\d{3,}?","12345678888888abc"))

輸出結果:

['1', '2', '3', '4', '5', '6', '7', '8', '8', '8', '8', '8', '8', '8']
['123', '456', '788', '888']

五、字符邊界

Python正則表達式字符邊界主要有四種:

^      開始位置
$      結束
\b     單詞邊界
\B     非單詞邊界
1. 字符串的開始和結束

案例:
輸入一個6位數字,必須要以95開頭,以8結尾的數字

print(re.findall(r"^95\d{3}8$","958348"))

輸出結果:

['958348']
2. 字符串的邊界

\b表示單詞的邊界,指某一個位置前后不都是字母、數字、下劃線(\w
案例:
輸入一句英文,找出里面以a、b、c開頭的單詞

str01 = "Use this toggle to the left to manage how your " \
        "browser uses BBC’s performance cookies. If you’re " \
        "outside the UK you can also use the toggle to set " \
        "your preferences for personalised advertising cookies."
pattern = re.compile(r"\b[abcABC][a-z]*\b")
print(pattern.findall(str01))

輸出結果:

['browser', 'cookies', 'can', 'also', 'advertising', 'cookies']

六、邏輯判斷

正則表達式中表示邏輯或的是用符號|,分為整體或和部分或
(1)整體或
案例:
簡單匹配身份證號,現在的身份證號是18位以前是15位,我們希望兩者都兼容;前面全是數字,最后一位可以是數字或者x

import re
print(re.findall("\d{14}[0-9x]|\d{17}[0-9x]]","34262219971012x"))

輸出結果:

['34262219971012x']

(2)部分或
案例:在一段英文句子中,找出es、er或者ing結尾的單詞

str01 = "Use this toggle to the left to manage how your " \
        "browser uses BBC’s performance cookies. If you’re " \
        "outside the UK you can also use the toggle to set " \
        "your preferences for personalised advertising cookies."
pattern = re.compile(r"\b[a-z]*(es|ing|er)\b")
print(pattern.findall(str01))

輸出結果:

['er', 'es', 'es', 'es', 'ing', 'es']

為什么沒有顯示出完整的單詞呢,這就涉及到正則表達式中分組的知識了;

七、 分組

1. 捕獲組與非捕獲組

分組是我們正則表達式中一個難點,把正則表達式的一部分用括號括起來作為一個組;主要包括捕獲組()非捕獲組(?:)
如何進行捕獲呢?待捕獲的表達式用小括號括起來,編號從1開始,后面通過反斜杠加數字標號進行調用。
我們以一個案例來進行解釋
案例:
在前一段英文中,匹配這樣的單詞,有5個字符;第一個字母和第五個一樣,第二個和第四個一樣,比如abcba
分析
因為匹配的是單詞第一個和最后一個都是單詞的邊界,故正則表達式的前后都用\b,第一個字母和第二個字母后面都要用到所以分別給它們設置捕獲組。用小括號括起來([a-z])([a-z])第三字母后面用不到所以不設置捕獲組,第四個字母和第五個字母調用前面的捕獲組,所以通過反斜杠加數字編號來進行調用,所以主要的正則表達式為:\b([a-z])([a-z])[a-z]\2\1\b

import re
print(re.findall(r"\b([a-z])([a-z])[a-z]\2\1\b","fdadd abcba"))

輸出結果:

[('a', 'b')]

貌似是匹配到了,但是輸出的結果并不滿意,并不是完整的顯示內容這是怎么回事呢?
原因
如果對正則表達式做了分組,使用findall函數則顯示捕獲組所匹配的內容,不能完整顯示,如果想完整顯示的話有兩個解決辦法:
方法一:使用非捕獲組
如果不需要對捕獲組的內容調用,可以使用非捕獲組,在表達式前加上?:就可以了,表示只捕獲數據了,只用來表達條件。回到我們前面的案例,英文句子中匹配單詞,怎樣才能完整顯示呢?對于后面不需要調用的正則表達式分組,我們使用非捕獲組的方式,就是表達式前加上問號和冒號即可,則前面的正則表達式\b[a-z]*(es|ing|er)\b可以寫成\b[a-z]*(?:es|ing|er)\b,這樣我們的輸出結果就是完整的單詞了。

方法二:使用迭代函數finditer
將findall函數改為迭代函數finditer

import re
match_result = re.finditer(r"\b([a-z])([a-z])[a-z]\2\1\b","fdadd abcba")
match_list = []
for i in match_result:
    match_list.append(i.group(0))
print(match_list)

輸出結果:

['abcba']

這樣就能完成顯示匹配結果了

2. 分組的命名

捕獲組默認是從數字1開始編號的,但是如果捕獲組數量多的話,最好還是能給捕獲組命名方便調用,那么怎么給捕獲組命名呢?
命名的方法:加問號加P跟著尖括號里寫上名稱(?P<名稱>);調用的方法:加問號加P等于號號碼跟上名稱(?P=name)
前面的正則表達式\b([a-z])([a-z])[a-z]\2\1\b命名可以寫成\b(?P<number01>[a-z])(?P<number02>[a-z])[a-z](?P=number02)(?P=number01)\b
實際代碼可以寫成:

print(re.findall(r"\b(?P<number01>[a-z])(?P<number02>[a-z])[a-z](?P=number02)(?P=number01)\b","fdadd abcba"))

八、零寬斷言

Python正則表達式的零寬斷言有著不同的稱呼:零寬度斷言、預搜索、環視等等,它是干嘛的呢?它是用來匹配一個位置
零寬的意思是不占用字符寬度、位置,比如\b表示單詞起始或者結束的位置,^表示正則表達式的開始;$表示正則表達式的結束;
零寬斷言的特征:
(1)做位置的匹配,不占寬度
(2)匹配的內容不計入最終的結果
(3)主要用作判斷某個位置的前后字符

1. 語法格式
圖片.png
2. 解釋

有一段字符串我們根據它前面的表達式來找到匹配的字符串,比如要在www.baidu.com中查找名稱baidu,我們可以根據條件聲明根域名是以www.開頭的,.com結尾的。那么零寬斷言的表達式就可以寫成(?<=www[.])[a-z]+(?=[.]com)
代碼示例

import re
print(re.findall(r"(?<=www[.])[a-z]+(?=[.]com)","www.baidu.com"))

輸出結果

['baidu']

注意:匹配輸出的內容是零寬斷言括號外面的部分

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373