熟悉正則表達式
# 正則表達式是對字符串操作的一種邏輯公式,使用事先定義好的一些'特定字符'及特定字符的'組合',組成一個'規(guī)則字符串' # 這個'規(guī)則字符串'表示對字符串(普通字符和特殊字符)操作的一種邏輯公式. # 作用: 1-給定字符串是否匹配正則表達式的過濾邏輯 2-通過正則表達式從字符串中獲取我們想要的特定部分 # 特點: 1-靈活,邏輯性和功能性強 2-用簡單的方式達到字符串的復雜控制 # 使用場景: 判斷手機號是否符合 判斷填寫的郵箱是否符合格式 # re模塊: 提供正則相關(guān)的操作
# 使用試例
msg1 = '杰倫德華趙本山'
# re.compile(pattern) pattern正則表達式 編譯一個正則表達式模式,返回一個pattern(正則表達式模式)對象
pattern1 = re.compile('趙本山')
# pattern.match(AnyStr) -> Match[AnyStr] | None (match:使匹配)
print(pattern1.match(msg1)) # None match()方法會從前往后進行匹配,如果不同則直接返回None
# 交換一下msg中要匹配的str的位置,就會改變輸出結(jié)果
msg2 = '趙本山杰倫德華'
pattern2 = re.compile('趙本山')
print(pattern2.match(msg2)) # <re.Match object; span=(0, 3), match='趙本山'> 匹配成功返回match對象
# 使用re模塊內(nèi)封裝的match()方法
# re.match(pattern, String):嘗試在字符串開頭匹配正則表達式,匹配到則返回Match對象,匹配不到則返回None
print(re.match('趙本山', msg1)) # None
print(re.match('趙本山', msg2)) # <re.Match object; span=(0, 3), match='趙本山'>
# re.search(pattern, String):掃描字符串,如果找到與正則表達式匹配則返回Match對象,如果沒有找到則返回None。
print(re.search('趙本山', msg1)) # <re.Match object; span=(4, 7), match='趙本山'>
print(re.search('趙本山', msg2)) # <re.Match object; span=(0, 3), match='趙本山'>
# 我們也可以接收這個Match對象,通過這個對象來操作里面的內(nèi)容
search_match = re.search('趙本山', msg1)
print(search_match.span()) # 返回與其相匹配的字符串位置 (4, 7)
print(search_match.group()) # 返回與其相匹配的字符串內(nèi)容 趙本山
正則表達式的基本操作
# 在熟悉了正則表達式的使用場景與用法,我們接下來就需要更靈活的去學習它.
'''
# '.': 用于匹配除換行符外(\n)的所有字符(寫在正則表達式中表示取反)
# '^': 用于匹配字符串的開始,即首行 如果沒有^則只從符合匹配條件的字符開始匹配
# '$': 用于匹配到字符串的結(jié)尾,(末尾如果有換行符\n,就匹配\n前面的那個字符),即行尾 如果沒有$則只匹配到符合需求的就不會匹配后面的字符
# 定義正則表達式驗證次數(shù)的符號:
# '*': 用于將前面的正則模式匹配0次或多次(貪婪模式:盡可能多的匹配) >=0
# '+': 用于將前面的正則模式匹配一次或多次(貪婪模式:盡可能多的匹配) >=1
# '?': 用于將前面的正則模式匹配0次或1次(貪婪模式:盡可能多的匹配) [0, 1]次
# '*?' '+?' '??': 表示上面三種字符的非貪婪模式:盡可能少的匹配
# '{m}': 用于驗證將前面的正則模式匹配m次
# '{m,}': 用于驗證將前面的正則模式匹配m次或多次 >=m
# '{m,n}': 用于將前面正則模式匹配m次到n次(貪婪模式),最小匹配m次,最大匹配n次
# '{m,n}?': 用于將前面正則模式匹配m次到n次(非貪婪模式),最小匹配m次,最大匹配n次
'''
# 正則表達式中的符號: # '[]': 用于標識一組字符,如果^是第一個字符,則表示的是一個補集.比如[0-9]表示所有數(shù)字,[^0-9]表示除數(shù)字外的字符
# 提取到符合 - '字母,數(shù)字,字母' - 這種規(guī)則的字符串出來
msg3 = 'a2fh23gw3eq8asf1h'
search_match = re.search('[a-z][0-9][a-z]', msg3)
print(search_match.group()) # a2f re.search()方法特點:只要找到第一個匹配正則的字符串,就停止匹配.(只能找到第一個符合正則的字符串)
# 如果需要找到所有符合條件的方法則使用re.findall(pattern, string)方法 # 將字符串中所有匹配項以列表形式返回
re_findall1 = re.findall('[a-z][0-9][a-z]', msg3)
print(re_findall1) # ['a2f', 'w3e', 'q8a', 'f1h']
# 如果不管字母中間有幾個數(shù)字的這種字符串都找到需要怎么辦呢?
re_findall2 = re.findall('[a-z][0-9]+[a-z]', msg3)
print(re_findall2) # 使用符號便可以完成我們的需求了 ['a2f', 'h23g', 'w3e', 'q8a', 'f1h']
# 通過幾個例子來了解上面符號的用法:
# QQ號碼驗證:5-11位,首位不能為0 '^[1-9][0-9]{4,10}$' 經(jīng)測試符合條件
QQ_num1 = '12345'
QQ_num2 = '1234'
QQ_num3 = '12345678901'
QQ_num4 = '123456789012'
result1 = re.match('^[1-9][0-9]{4,10}$', QQ_num1)
result2 = re.match('^[1-9][0-9]{4,10}$', QQ_num2)
result3 = re.match('^[1-9][0-9]{4,10}$', QQ_num3)
result4 = re.match('^[1-9][0-9]{4,10}$', QQ_num4)
print(result1) # <re.Match object; span=(0, 5), match='12345'>
print(result2) # None
print(result3) # <re.Match object; span=(0, 10), match='12345678901'>
print(result4) # None
# 用戶名可以是字母或數(shù)字,不能以數(shù)字開頭,用戶名必須6位以上 [0-9a-zA-Z]
username1 = '00admin' # 數(shù)字開頭
username2 = 'admin&*' # 加特殊符號
username3 = 'admin' # 正常用戶名
print(re.match('[a-zA-Z][0-9a-zA-Z]', username1)) # None
print(re.match('[a-zA-Z][0-9a-zA-Z]', username2)) # <re.Match object; span=(0, 2), match='ad'>
print(re.match('[a-zA-Z][0-9a-zA-Z]', username3)) # <re.Match object; span=(0, 2), match='ad'>
# 如果我們不使用$符號的話,可以看到不符合規(guī)則的username2也匹配成功了,這時候我們在末尾加上$測試
print(re.match('[a-zA-Z][0-9a-zA-Z]$', username2)) # None 當加上$表示要一直匹配到字符串結(jié)尾,這樣加上特殊符號的username2就不符合條件了
# 由于match()函數(shù)是從頭開始匹配字符串的,所以我們不需要使用^符號,那么我們使用search函數(shù)測試一些username1的效果是什么呢?
print(re.search('[a-zA-Z][0-9a-zA-Z]', username1)) # <re.Match object; span=(2, 4), match='ad'> 數(shù)字開頭也顯示匹配成功
# 原因是沒有^符號,search函數(shù)只要在字符串中匹配到符合正則的字符就會返回,所以我們加上^符號,要求從頭匹配.
print(re.search('^[a-zA-Z][0-9a-zA-Z]', username1)) # None
# 通過上面兩個例子我們應該理解了符號'^'和'$'的使用方法了: '^...$'表示從頭到尾,拿整個字符串進行匹配!
# 那有沒有什么能代替上面比較麻煩的書寫呢?還真有:
'''
# \A: 表示從字符串的開始處匹配
# \Z: 表示從字符串的結(jié)束處匹配,如果存在換行,只匹配到換行前的結(jié)束字符串
# \b: 匹配一個單詞邊界,指單詞和空格間的位置,例:'py\b'可以匹配'python'中的py,但不能匹配'openpyxxm'中的py
# \B: 匹配一個非單詞邊界,'py\B'可以匹配'openpyxxm'中的py,但不能匹配'python'中的py
# \d: 匹配任意數(shù)字,等價于[0-9]
# \D: 匹配任意非數(shù)字,等價于[^\d]
# \s: 匹配任意空白字符,等價于[\t\n\r\f]
# \S: 匹配任意非空白字符,等價于[^\s]
# \w: 匹配任意字母數(shù)字及下劃線,等價于[0-9a-zA-Z_]
# \W: 匹配任意非字母數(shù)字及下劃線,等價于[^\w]
# \\: 匹配反斜杠'\'
'''
# 那使用上面學到的重新寫一個正則表達式看看效果 # 用戶名符合字母數(shù)字下劃線,不能以數(shù)字開頭且用戶名長度大于6: # 如果要使用整個字符串進行比較:由于match是從頭開始的,所以只需要在末尾加$,search函數(shù)的話需要開頭加^末尾加$
username4 = '00admin'
username5 = 'admin00'
print(re.match('[a-zA-Z]\w{5,}$', username4)) # None
print(re.match('[a-zA-Z]\w{5,}$', username5)) # <re.Match object; span=(0, 7), match='admin00'>
# 從一列字符串中找到.py文件:
str1 = 'aa.py bb.py cc.py apy.txt'
print(re.findall(r'py\b', str1)) # ['py', 'py', 'py', 'py'] 需要加上文件名
print(re.findall(r'\w\.py\b', str1)) # ['a.py', 'b.py', 'c.py'] 文件全名沒匹配到
print(re.findall(r'\w*\.py\b', str1)) # ['aa.py', 'bb.py', 'cc.py'] 匹配成功
# 手機號碼驗證:
phone_num = '15233779988'
print(re.match(r'1[35789]\d{9}$', phone_num)) # <re.Match object; span=(0, 11), match='15233779988'>
正則表達式的分組
# 分組
'''
'|': 表示或者功能
'[adc]': 表示元素范圍內(nèi)單個的或者(a or b or c)
'(word1 | word2)': 表示整體范圍內(nèi)的或者(word1 or word2) 可以通過group(第幾組)方法得到內(nèi)容
'''
# 驗證輸入的郵箱格式 @163.com @qq.com @126.com
email_num1 = 'otto666@qq.com'
email_num2 = '666otto@163.com'
email_num3 = '66otto6@126.com'
print(re.match(r'\w{6,20}@(163|QQ|qq|126)\.(com|cn)$',
email_num1)) # <re.Match object; span=(0, 14), match='otto666@qq.com'>
print(re.match(r'\w{6,20}@(163|QQ|qq|126)\.(com|cn)$',
email_num2)) # <re.Match object; span=(0, 15), match='666otto@163.com'>
print(re.match(r'\w{6,20}@(163|QQ|qq|126)\.(com|cn)$',
email_num3)) # <re.Match object; span=(0, 15), match='66otto6@126.com'>
# 不以7結(jié)尾的手機號碼
phone1 = '15233448877'
phone2 = '15233448888'
print(re.match(r'1\d{9}[1-689]$', phone1)) # None
print(re.match(r'1\d{9}[1-689]$', phone2)) # <re.Match object; span=(0, 11), match='15233448888'>
# match.group(): group方法可以獲得不同組的信息 # 通過數(shù)字分組引用: # 將電話的區(qū)號和號碼分別提取出來
phone3 = '010-12644448888'
re_match = re.match(r'(\d{3}|\d{4})-(\d{8,12})$', phone3)
print(re_match) # <re.Match object; span=(0, 15), match='010-12644448888'>
print(re_match.group()) # 010-12644448888
# ()表示分組,group(1)表示提取出第一組的內(nèi)容
print(re_match.group(1)) # 010
print(re_match.group(2)) # 12644448888
# 從標簽頁中提取出信息 '.'表示所有字符 </1>表示匹配第一組的內(nèi)容 如第一組內(nèi)容位<html>則<1> = </html>
msg1 = '<h1>hello world</h1>'
re_match1 = re.match(r'<([0-9a-zA-Z]+)>(.+)</\1>$', msg1)
print(re_match1) # <re.Match object; span=(0, 20), match='<h1>hello world</h1>'>
print(re_match1.group()) # <h1>hello world</h1>
print(re_match1.group(1)) # h1
print(re_match1.group(2)) # hello world
msg2 = '<h1>hello world</h2>'
re_match2 = re.match(r'<([0-9a-zA-Z]+)>(.+)</\1>$', msg2)
print(re_match2) # None 因為</\1>的判定前后標簽不一致,匹配不成功返回None
msg3 = '<h1><h2>hello world</h2></h1>'
re_match3 = re.match(r'<([0-9a-zA-Z]+)>(.+)</\1>$', msg3)
print(re_match3)
print(re_match3.group(2)) # <h2>hello world</h2>
# 如果是多個嵌套的標簽體,我們怎么得到中間的信息呢? # 方法是我們也多嵌套一層正則表達式
re_match3 = re.match(r'<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)</\2></\1>$', msg3)
print(re_match3.group(1)) # h1
print(re_match3.group(2)) # h2
print(re_match3.group(3)) # hello world 成功拿到!
# 但當上面嵌套過于復雜時,很容易出現(xiàn)看串的情況,這里需要怎么優(yōu)化一下呢? # 起名的方式解決: (?P<name>正則) (?P=name)
msg4 = '<h1><h2>hello world</h2></h1>'
re_match4 = re.match(r'<(?P<name1>[0-9a-zA-Z]+)><(?P<name2>[0-9a-zA-Z]+)>(.+)</(?P=name2)></(?P=name1)>', msg4)
print(re_match4) # <re.Match object; span=(0, 29), match='<h1><h2>hello world</h2></h1>'>
print(re_match4.group(3)) # hello world
# 其余re方法
# re.sub(正則表達式, 新內(nèi)容, string):將正則表達式匹配到的內(nèi)容替換為新內(nèi)容
re_sub1 = re.sub(r'\d+', '99', '數(shù)學:59 英語:59')
print(re_sub1) # 替換結(jié)果: 數(shù)學:99 英語:99
# 新內(nèi)容部分也可以放函數(shù)進行運算
def numplus(temp):
# temp.group()相當于匹配正則取出的結(jié)果
num = temp.group()
num1 = int(num)
num1 += 1
return str(num1)
re_sub2 = re.sub(r'\d+', numplus, '數(shù)學:59 英語:59')
print(re_sub2) # 數(shù)學:60 英語:60 執(zhí)行函數(shù)后的運行結(jié)果!
# re.split(正則, string)
re_split = re.split(r'[,:]', '數(shù)學:59 英語:59')
print(re_split) # ['數(shù)學', '59 英語', '59']
# 貪婪模式: 總是盡可能多的去匹配
msg5 = 'abc123abc'
print(re.match(r'abc(\d+)', msg5)) # <re.Match object; span=(0, 6), match='abc123'>
print(re.match(r'abc(\d*)', msg5)) # <re.Match object; span=(0, 6), match='abc123'>
print(re.match(r'abc(\d?)', msg5)) # <re.Match object; span=(0, 4), match='abc1'>
# re中方法總結(jié)
match(pattern, string) 從開頭開始匹配,匹配一次
search(pattern, string) 整個字符串匹配一次就完事
findall(pattern, string) 整個字符串全部匹配
sub(pattern, new, str) 替換
split(pattern, str) 切割
文章來源地址http://www.zghlxwxcb.cn/news/detail-419904.html
文章來源:http://www.zghlxwxcb.cn/news/detail-419904.html
到了這里,關(guān)于從零學習python - 14正則表達式的始末的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!