1??正則表達(dá)式語法
正則表達(dá)式是用匹配或者描述字符串的工具
用處:
a.判斷字符串是否滿足某個條件---判斷輸入的字符串是否是/手機(jī)號碼承桥。是否是ip地址
b.提取滿足條件的字符串
c.字符串替換
python中通過re模塊中相應(yīng)的方法來支持正則表達(dá)式的匹配梨树、查找和替換等功能
from re import fullmatch
#fullmatch(正則表達(dá)式字符串, 字符串) --> 判斷正則表達(dá)式和字符串是否完全匹配
#正則表達(dá)式字符串:就是一個字符串,字符串中是正則表達(dá)式語法。r'正則表達(dá)式'
#正則表達(dá)式中包含兩個部分渠抹,一個是正則語法對應(yīng)的字符慨代,第二個是普通字符
# 1 .(匹配任意字符)
#一個.只匹配一個任意字符
# 匹配一個字長度是3的符串,第一個字符是'a',第二個字符是任意字符掂咒,最后一個字符是'b'
re_str = r'a.b'
print(fullmatch(re_str, 'adb'))
# 2 \w(匹配字母數(shù)字下劃線)
#一個\w匹配一個字符
# 匹配第一個字符是數(shù)字或者下劃線,后面三個字符是任意對象字符串
re_str1 = r'\w...'
print(fullmatch(re_str1, '08js'))
# 3\s(匹配任意空白字符)
#空白字符:空格迈喉、制表符绍刮、回車(執(zhí)行), 都輸入空白符
# 匹配第一個字符是a挨摸,第二個字符是空白孩革,最后一個字符b的字符串
re_str2 = r'a\sb'
print(fullmatch(re_str2, 'a b'))
# 4 \d(匹配數(shù)字字符)
re_str = r'\d\d\d'
print(fullmatch(re_str, '123'))
# 5 \b(檢測邊界)
#一個\b不回去匹配一個字符,而是單純的檢測\b出現(xiàn)的位置是否是單詞邊界
#單詞邊界:字符串開始和結(jié)尾得运、空格嫉戚、換行、標(biāo)點(diǎn)符號等澈圈,可以將兩個單詞隔開的字符都是單詞邊界
abc
re_str3 = r'\babc'
re_str = r'abc\b\saaa' # 匹配一個字符串前三位是abc彬檀,第四位是空白字符,后面是aaa瞬女。并且要求c后面是單詞邊界
result = fullmatch(re_str3, 'abc')
print(result)
# 6^(檢測是否是字符串開頭)
re_str = r'^\d\d\d+' # 判斷一個字符串是否是三個數(shù)字開頭
result = fullmatch(re_str, '221234')
print(result)
# 7 $(檢測是否是字符串結(jié)尾)
re_str = r'\dabc$'
result =fullmatch(re_str, '1abc')
print(result)
# 8 \W(匹配第一個字符非數(shù)字字母下劃線)
re_str = r'\Wabc'
result = fullmatch(re_str, '#abc')
print(result)
# 9 \S(匹配非空白字符)
re_str = r'\S...'
result = fullmatch(re_str, '12w2')
print(result)
# 10 \D(匹配非數(shù)字字符)
re_str = r'\D\w\w\w'
result = fullmatch(re_str, 'w12r')
print(result)
# 11 \B(檢測是否不是單詞邊界)
re_str = r'ad\Bwr'
result = fullmatch(re_str, 'adwr')
print(result)
# 12 [](匹配中括號中出現(xiàn)的任意一個字符)
#一個中括號匹配一個字符
#[字符集] --> 匹配一個字符窍帝,這個字符是字符集中的任意一個字符
#[abc], [\d+]
#[字符1-字符2] -->匹配一個字符,這個字符是Unicode編碼值在字符1到字符2中的任意字符
#[1-9] -->數(shù)字1到9 [a-z] -->小寫字母 -->[A-Z] -->大寫字母
#注意:-在中括號中诽偷,如果放在兩個字符之間表示范圍坤学。
# 匹配一個第一個字符是a或者b或者c,后面aaa
re_str = r'[abc]+aaa'
result = fullmatch(re_str, 'caacaccaaa')
print(result)
re_str = r'[1-4]\d\d\d'
result = fullmatch(re_str, '1234')
print(result)
# 13 [^字符集](匹配一個不再字符集中的任意字符)
#注意:^必須放在中括號中的最前面才有效
re_str = r'[^abc]...' # 匹配一個四位的字符串,第一位不是abc的任意一個报慕,后面三位是任意字符
result = fullmatch(re_str, 'rqw2')
print(result)
2??正則表達(dá)式次數(shù)相關(guān)的符號
from re import fullmatch
# 1 *(匹配0次或者多次)
"""
字符* --> 字符出現(xiàn)0次或者多次
"""
re_str = r'\d*'
print(fullmatch(re_str, '124'))
# 用正則表達(dá)式來檢測一個標(biāo)識符是否符合要求
re_str = r'[a-zA-Z_]\w*'
print(fullmatch(re_str, '_s1a12d'))
# 2 +(匹配一次或者多次)
# abc前面有一個或者多個數(shù)字的字符串
re_str = r'\d+abc'
print(fullmatch(re_str, '1abc'))
# 3. ?(匹配0次或者一次)
re_str = r'a?123'
print(fullmatch(re_str, 'a123'))
# 練習(xí):寫一個正則表達(dá)式深浮,匹配所有的整數(shù)
re_str = r'[+-]?[1-9]\d*'
print(fullmatch(re_str, '167'))
# 4. {}(指定次數(shù))
"""
{N} --> 匹配N次
{M,N} --> 匹配M到N次
{M,} --> 至少匹配M次
{,N} --> 最多匹配N次
"""
re_str = r'\d{3,}'
print(fullmatch(re_str, '123'))
re_str = r'\d{2,5}'
print(fullmatch(re_str, '12233'))
# 判斷密碼是否符合要求:密碼是有數(shù)字和字母組成,并且位數(shù)輸6-16位
re_str = r'[0-9a-zA-Z]{6,16}'
print(fullmatch(re_str, '01231dddds.'))
三分之和組合
import re
# 1. |(分之)
"""
條件1|條件2 --> 先用條件1去匹配眠冈,如果匹配成功了飞苇。如果條件1匹配失敗,用條件2去匹配蜗顽。
注意:如果條件1匹配成功就不會用條件2再去匹配
"""
re_str = r'[a-z]{3}|[A-Z]{3}'
print(re.fullmatch(re_str, 'ASF'))
#
re_str = r'abc(H|K|L)'
print(re.fullmatch(re_str, 'abcK'))
# 2()(分組)
"""
a.組合(將括號中的類容作為一個整體進(jìn)行操作)
b.捕獲 --> 使用帶括號的正則表達(dá)式匹配成功后布卡,只獲取括號中的內(nèi)容
c.重復(fù) --> 在正則表達(dá)式中可以通過\數(shù)字來重復(fù)前面()中匹配到的結(jié)果.數(shù)字代表前面的第幾個分組
"""
# 2d3f4g 匹配一個字符串,以數(shù)字字母的組合出現(xiàn)三次
re_str = r'(\d[a-zA-Z]){3}'
print(re.fullmatch(re_str, '1o2i3i'))
print(re.findall(re_str, '1o1o1o'))
# c.重復(fù)
re_str = r'([a-z]{3})-\1'
print(re.fullmatch(re_str, 'asd-asd'))
# 3.轉(zhuǎn)義符號
"""
正則表達(dá)式中可以通過在特殊的符號前加\雇盖,來讓特殊的符號沒有意義
. + * ? ^ $ 等有特殊的功能
??注意:在中括號中有特殊功能的符號忿等,只代表符號本身
\ 不管在哪都需要轉(zhuǎn)義
- 在[]外面沒有特殊功能,在[]中要表示-本身崔挖,就不要放在兩個字符之間
()需要轉(zhuǎn)義
"""
re_str = r'\.abc'
print(re.fullmatch(re_str, '.abc'))
4??模塊中的函數(shù)
import re
# 1. compile
"""
compile(正則表達(dá)式字符串) --> 將正則表達(dá)式字符串轉(zhuǎn)換成正則表達(dá)式對象
"""
re_objct = re.compile(r'\d+')
print(re_objct)
print(re_objct.fullmatch('23738'))
# 2. fullmatch和match
"""
fullmatch(正則表達(dá)式字符串, 字符串)
--> 用正則表達(dá)式去完全匹配字符串(匹配整個字符串)贸街,返回匹配對象(SRE_Match)或者None
match(正則表達(dá)式字符串, 字符串)
--> 匹配字符串開頭,返回匹配對象或者None
"""
result = re.fullmatch(r'\d([a-zA-Z]+)123', '2hjdh123')
print('111',result)
# 1.span(group=0) --> 獲取匹配成功的區(qū)間(左閉右開區(qū)間)
print(result.span(z))
print(result.start(1)) # 獲取匹配到的開始下標(biāo)
print(result.end(1)) # 獲取匹配到的結(jié)束下標(biāo)后的下標(biāo)
# 2.group(group = 0) --> 獲取匹配結(jié)果
"""
group()/group(0) --> 獲取正則表達(dá)式完全匹配的結(jié)果
group(index>0) --> 獲取正則表達(dá)式中第group個分組匹配到的結(jié)果
"""
print('0:',result.group())
print('1:',result.group(1))
# 3.string --> 獲取被匹配的原字符串
print(result.string)
result = re.match(r'\d([a-zA-Z]+)123', '2hjdh123ABC')
print('match:',result)
# 3.search
"""
search(正則表達(dá)式, 字符串)
--> 查找字符串中滿足正則表達(dá)式的第一個字符串庵寞。返回值是匹配對象或者None
"""
result = re.search(r'(\d)[a-zA-Z]+', 'uhsh2hdje+984nf')
print(result.group(0))
print(result.group(1))
print(result.string)
# 練習(xí):使用search匹配出一個字符串中所有的數(shù)字字符串
# 'abc34jshd8923jkshd9lkkk890k' --> 34,8923薛匪,9皇帮,890
re_str = r'\d+'
str1 = 'abc34jshd8923jkshd9lkkk890k'
result = re.search(re_str, str1)
while result:
print(result)
str1 = str1[result.end():]
result = re.search(re_str, str1)
# 4.findall
"""
findall(正則表達(dá)式, 字符串) --> 獲取字符串中滿足正則表達(dá)式的所有的子串,返回一個列表
注意:如果正在表達(dá)式中有分組蛋辈,取值的時候只取分組中匹配到的結(jié)果;
如果有多個分組,會將每個分組匹配到的結(jié)果作為一個元祖的元素
"""
re_str = r'(\d+)k([a-d]+)'
str1 = 'abc34kshd8923kabcshd9lkkk890kaa'
result = re.findall(re_str, str1)
print(result) # [('8923', 'abc'), ('890', 'aa')]
re_str = r'(\d+)k[a-d]+'
str1 = 'abc34kshd8923kabcshd9lkkk890kaa'
result = re.findall(re_str, str1)
print(result) # ['8923', '890']
re_str = r'\d+k[a-d]+'
str1 = 'abc34kshd8923kabcshd9lkkk890kaa'
result = re.findall(re_str, str1)
print(result) # ['8923kabc', '890kaa']
# 5.finditer
"""
finditer(正則表達(dá)式, 字符串)
--> 查找所有滿足正則條件的子串将谊,返回值是迭代器冷溶,迭代器中的元素是匹配對象
"""
re_str = r'\d+'
str1 = 'abc34kshd8923kabcshd9lkkk890kaa'
result = re.finditer(re_str, str1)
print(result)
for item in result:
print(item)
# 6. split
"""
split(正則表達(dá)式,字符串) --> 將字符串按照滿足正則表達(dá)式條件的子串進(jìn)行分割
"""
str1 = 'ahsb1sssa8-jjhd7nhs+90nsjhf3-4hhh7+8kjj-'
result = re.split(r'[-+]', str1)
print(result)
# 7.sub
"""
sub(正則表達(dá)式,repl,字符串) --> 將字符串中滿足正則表達(dá)式條件的子串替換成repl。返回替換后的字符串
"""
str1 = 'hsj8jskfh98ssjj8hshh'
result = re.sub(r'\d+','*', str1)
print(result)
str1 = '智 障,你在干嘛尊浓?逼, 后視鏡逞频,媽的加扣扣上'
result = re.sub(r'傻\s*叉|逼|fuck|媽的|智\s*障', '*', str1)
print(result)
5??歌詞解析
"""
需求:播放指定歌曲的時候,給一個時間栋齿,能夠把這首歌在這個時間對應(yīng)的詞返回
面向?qū)ο螅赫乙粋€類苗胀,讓他擁有解析歌詞的功能
"""
class Lyrics:
# 歌詞類
def __init__(self, time='', word=''):
self._time = time
self.word = word
def __repr__(self):
return str(self.__dict__)
@property
def time(self):
return self._time
@time.setter
def time(self, value):
fen = float(value[1:3])
miao = float(value[4:])
self._time = fen * 60 + miao
def __gt__(self, other):
return self._time>other._time
class AnalysisLyric:
# 歌詞解析類
def __init__(self, name):
self.name = name # 歌名
self.all_lyric = [] # 保存當(dāng)前解析出得歌詞
# 分離歌詞和時間
def __split_time_word(self, line):
lines = line.split(']')
# print(lines[-1])
# 獲取每一行的詞
word = lines[-1]
# 便利獲取每一行的時間
for time in lines[:-1:]:
# 根據(jù)時間和詞創(chuàng)建歌詞對象
ly_obj = Lyrics(word=word)
ly_obj.time = time
self.all_lyric.append(ly_obj)
# 根據(jù)時間獲取歌詞
def get_lyrics(self, time: int):
try:
with open('./'+self.name+'.txt', 'r', encoding='utf-8') as f:
line = f.readline()
while line:
# print(line)
lyric = self.__split_time_word(line)
line = f.readline()
self.all_lyric.sort(reverse=True)
# print(self.all_lyric)
for item in self.all_lyric:
if item.time < time:
return item.word
except FileNotFoundError:
print('沒有相應(yīng)的歌詞!')
lyh_ly = AnalysisLyric('藍(lán)蓮花')
print(lyh_ly.get_lyrics(17))