目录
【2】使用search()方法进行匹配:在整个字符串中搜索第1个匹配的值
【3】使用findall()方法进行匹配:在整个给定字符串中,搜索所有符合正则规则的字符串
练习题2:ls= ['123我','_咋hello','这php','么','不帅789','呢???']
1.正则表达式:☆
# 专门用来处理字符串的一个规则
定义:记录文本规则的代码
需求:判断用户名长度为8-16位
改变需求:长度为8-16位,字符只能是英文数字下划线,且要大写字母开头 ☆
用代码怎么实现?其实能实现,只是很麻烦!(思路是利用ASCII码)
麻烦,就违背了编程的宗旨:那如何简单呢?就需要用正则表达式处理!☆
1.1 正则写法快速入门:
# 分析:学习思路,就是学习pattern这个规则 ☆
① 常用正则符号:☆
^开头
$结尾
. 表示任意一个字符
* 表示0个或多个
+ 表示1个或多个
? 表示0个或1个
{n} 表示重复n次
{n,} 表示至少重复n次
{n,m} 表示重复n-m次
import re
a = 'lhellloll,llll'
pattern = "l{2,}"
res = re.findall(pattern,a)
print(res)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_01.py
['lll', 'll', 'llll']
"""
[xyz] 表示取x或取y或取z
[0-9] 表示取任意一个数字
[a-z] 表示取任意一个小写字母
[A-Z] 表示取任意一个大写字母
[^xyz] 表示取反,除了xyz取其他
[\u4e00-\u9fa5] 表示取任意一个汉字
| 表示选择,或者
\ 表示转义符
r 表示原生字符串:写在规则前面(结论:规则前要加r)
# 可以理解为固定写法:有的需要转义,有的不需要,就直接写r就全不要了
import re
str1 = "hello,xyz,123,789,黑龙江省,哈尔滨市!\d"
pattern = r"\\d"
res = re.findall(pattern,str1)
print(res)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/复习/正则表达式/demo1.py
['\\d']
"""
import re
str1 = "hello,xyz,123,789,黑龙江省,哈尔滨市!\d"
#pattern = r"\\d"
#pattern = r"hello"
pattern = "hello|xyz"
res = re.findall(pattern,str1)
print(res)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/复习/正则表达式/demo1.py
['hello', 'xyz']
"""
1.1.1 利用原生字符r“\()” 规则:
为确保避免不必要的麻烦,还是建议用这个写法:
pattern =re.compile(r'规则')
pattern = r"\w+" ,这个虽然也可以,但是总感觉有问题。
\d 匹配数字 \D匹配非数字
\w 匹配英文、数字、下划线、汉字 \W匹配非英文、数字、下划线、汉字
import re
str = 'hello,123,美女,___!'
pattern = r"\w+" #匹配一个或多个英文,数字,下划线,汉字
res = re.findall(pattern,str)
print(res)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_01.py
['hello', '123', '美女', '___']
"""
\s 匹配空白符 \S匹配非空白(不包括换行)
import re
str = 'he llo'
pattern = r"\s" #匹配空格
res = re.findall(pattern,str) #str中有多少个空格就会返回多少个空格
print(res)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_01.py
[' ', ' ', ' ']
"""
\b 匹配单词的开始或结束,单词分界符通常是空格、标点符号、换行
import re
str1 = 'hello,abxx'
str2 = "hello,ab123"
str3 = "hello,abc__我"
str4 = "hello,cd456"
pattern = r"ab\w+" #匹配出以ab开头的内容
print(re.findall(pattern,str1))
print(re.findall(pattern,str2))
print(re.findall(pattern,str3))
print(re.findall(pattern,str4))
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_01.py
['abxx']
['ab123']
['abc__我']
[]
"""
从下面的例子可以看出,在做匹配的时候,re会以逗号作为单词的分隔符。
import re
str1 = 'hello,abxx'
str2 = "hello,ab123"
str3 = "hello,abc__我"
str4 = "hello,cd456"
pattern = r"ab\w+" #以ab开头的内容
print(re.findall(pattern,str1))
pattern2 = r"我$" #以“我”结尾
print(re.findall(pattern2,str3))
pattern3 = r"^hello" #以hello开头
print(re.findall(pattern3,str3))
print(re.findall(pattern,str4))
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_02.py
['abxx']
['我']
['hello']
[]
"""
② 使用re模块实现正则表达式:
re模块常用的5个方法☆ match/findall/search/split/sub
【1】使用match()方法进行匹配:
从字符串开始处匹配,匹配成功返回Match对象,失败返回None
import re
#需求:匹配字符串是以hello开头的
str1 = "hello,world"
str2 = "world,hello"
str3 = "hello"
pattern = r"hello.*"
print(re.match(pattern,str1).group())
print(re.match(r"hello.*",str1).group())
#以上两种方式等价
print(re.match(r"hello.*",str1))
print(re.match(r"hello.*",str2))
print(re.match(r"hello.*",str3))
print(re.match(r"hello.*",str3).group())
#group() 返回匹配内容
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_02.py
hello,world
hello,world
<re.Match object; span=(0, 11), match='hello,world'>
None
<re.Match object; span=(0, 5), match='hello'>
hello
Process finished with exit code 0
"""
import re #将正则表达式翻译成pattern对象 pattern = re.compile(r'\d+') result = re.match(pattern,'1234abcdef') if result: print(result.group()) else: print("匹配失败!") print(re.match(r'\w+1234','abcdef1234').group()) print(re.match(r'.*1234','abcdef1234').group()) """ D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_03.py 1234 abcdef1234 abcdef1234 """
【1.1】正则表达式的pattern对象
#pattern = r'(\w+) (\w+) (?P<word>.*)'
pattern =re.compile(r'(\w+) (\w+) (?P<word>.*)') 由下面的整个程序发现这两种规则是由差别的。
import re
#正则表达式的pattern对象
#pattern = r'(\w+) (\w+) (?P<word>.*)'
pattern =re.compile(r'(\w+) (\w+) (?P<word>.*)')
match = pattern.match("I am eating")
print("返回匹配的原始字符:",match.string) #返回匹配的原始字符
print("返回匹配的规则:",match.re) #返回匹配的规则
print("获取匹配的开始索引:",match.pos) #获取匹配的开始索引
print("获取匹配结束的索引:",match.endpos) #获取匹配结束的索引
print("最后的索引:",match.lastindex) #最后的索引
print("分组别名:",match.lastgroup) #分组别名
print("以元组形式返回字符:",match.group(1,2,3)) #以元组形式返回字符
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_03.py
返回匹配的原始字符: I am eating
返回匹配的规则: re.compile('(\\w+) (\\w+) (?P<word>.*)')
获取匹配的开始索引: 0
获取匹配结束的索引: 11
最后的索引: 3
分组别名: word
以元组形式返回字符: ('I', 'am', 'eating')
Process finished with exit code 0
"""
注意:pattern =re.compile(r'(\w+) (\w+) (?P<word>.*)')
该句中的 (?P<word>.*)是给最后一个分组起别名的意思,r'(\w+) (\w+) (?P<word>.*)' 这当中一共有三组。
修改代码:
import re #正则表达式的pattern对象 pattern =re.compile(r'(?P<word1>.*) (?P<word2>.*) (?P<word3>.*)') match = pattern.match("I am eating") print("分组别名:",match.lastgroup) #分组别名(最后一个分组的别名) print("获取以各组别名为键,以匹配值为值的字典:",match.groupdict()) #获取以各组别名为键,以匹配值为值的字典 print("以元组形式返回字符:",match.group(1,2,3)) #以元组形式返回字符 """ D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_03.py 分组别名: word3 获取以各组别名为键,以匹配值为值的字典: {'word1': 'I', 'word2': 'am', 'word3': 'eating'} 以元组形式返回字符: ('I', 'am', 'eating') """
match.groupdict() #获取以各组别名为键,以匹配值为值的字典
match.group(1,2,3) #以元组形式返回字符
match.lastgroup) #分组别名(最后一个分组的别名)
import re
#正则表达式的pattern对象
pattern =re.compile(r'(?P<word1>.*) (?P<word2>.*) (?P<word3>.*)')
match = pattern.match("I am eating")
print(match.start(1)) #默认起始位置为0
print(match.start(0)) #默认起始位置为0
print(match.end(3)) #默认最后一个索引+1
str1 = "I am eating"
print(str1[match.start(1):match.end(3)])
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_03.py
0
0
11
I am eating
"""
print(match.start(n)) #默认起始位置为0 n表示从第几组开始(0,1都是初始位置组)
【1.3】贪婪模式与非贪婪模式
import re #贪婪模式与非贪婪模式 ''' 懒惰模式 *? 重复任意次,但尽可能少重复 +? 重复一次 但尽可能少重复 ?? 重复0到1次,尽可能少重复 {m,n}? 重复m,n次 尽可能少重复 {n,}? 重复n次以上 尽可能减少重复 ''' content = "<table><tr><td>你们好</td></tr><tr><td>你们好</td></tr><tr><td>你们好</td></tr><tr><td>你们好a</td></tr></table>" print(re.findall(r"<td>(.*)</td>",content)) #贪婪模式 print(re.findall(r"<td>(.*?)</td>",content))#非贪婪
【2】使用search()方法进行匹配:在整个字符串中搜索第1个匹配的值
【3】使用findall()方法进行匹配:在整个给定字符串中,搜索所有符合正则规则的字符串
import re
#需求:匹配字符串中以py开头的内容
str1 = "hello,py_css,py_html,python,ty_java,my_py,my_py_you"
pattern = r"py\w+"
print(re.search(pattern,str1).group()) #只取符合规则的第一个内容
print(re.findall(pattern,str1)) #取出所有符合的内容,并以列表的形式返回
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_02.py
py_css
['py_css', 'py_html', 'python', 'py_you']
"""
【4】使用sub()替换字符串:
import re
#需求:将电话号码替换成1xxxxxxxxxx
str1 = "恭喜15778475303的用户,成为奈克瑟斯的第99999个转生者"
pattern = r"1[3456789]\d{9}" #表示str1中的电话号码
str1 = re.sub(pattern,"1xxxxxxxxxx",str1)
print(str1)
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_02.py
恭喜1xxxxxxxxxx的用户,成为奈克瑟斯的第99999个转生者
"""
【5】使用split()分割字符串:
re.split(pattern,string,flag) 能够将字符串按规则进行分割,并且以列表的形式返回 。
import re
#需求:以@#?!分割字符
str1 = "lkw?naruto@163#.com"
patern = r"[@!#?]"
print(re.split(patern,str1))
"""
D:\Anaconda3\python.exe D:/Python_file_forAnconda3_python/base_python/python_re_02.py
['lkw', 'naruto', '163', '.com']
"""
练习:
import re
data =re.findall(r'abcd','abcde')
print(data)
#data2 =re.findall(r'a[0-3]7','a27')
data2 = re.findall(r'a[a-z]7','ac7')
print(data2)
#匹配字符串的数字 \d
#data3 = re.findall(r'a\dc','a2c')
data3 = re.findall(r'a\d+c','a22222c')
print(data3)
#匹配非数字 \D
data4 = re.findall(r'a\Dc','aec')
print(data4)
#匹配空字符串 \s空字符,或者是\n\t\f\v(换行,制表符)
print(re.findall(r'a\sc',"a c"))
#匹配非空字符 \S
print(re.findall(r'a\Sc',"abc"))
#匹配单词字符 \w【A-Z,a-z,0-9_】
print(re.findall(r'a\wc','abc'))
#匹配非单词字符 \W
print(re.findall(r'a\Wc','a+c'))
# * 匹配前一个字符0或无限次
print(re.findall(r'abc*','ab'))#['ab']
# + 匹配前一个字符1或无限次
print(re.findall(r'abc+','abc'))
# {m} 匹配前一个字符m次
print(re.findall(r'ab{5}c','abbbbbc'))#['abbbbbc']
# {m,n} 匹配前一个字符m次到n次
print(re.findall(r'ab{3,5}c','abbbc'))#['abbbc']
#匹配字符串开头
print(re.findall(r'^ab','abbbc'))#['ab']
#print(re.findall(r'^aab','abbbc'))#[]
#匹配字符串结尾
print(re.findall(r'bc$','abbbc'))#['bc']
#print(re.findall(r'bc$','abbbcc'))#[] 即,若匹配的不是以bc结尾,则返回 空
# | 代表左右表达式中任意匹配一个,它总是先尝试匹配左边的表达式,一旦成功会跳过匹配右边的表达式
#如果 | 没有被包括在()中,则它的范围是整个表达式
print(re.findall(r'(abc|def)','abc'))
print(re.findall(r'abc|def','abcdef'))#['abc', 'def']
print(re.findall(r'a(123|456)c','a456c'))#['456']
txt = '<a>appl</a>'
res = re.findall(r'<a>(.*?)</a>',txt)
print(res)#['appl']
#匹配手机号
print(r'^1[0-9]{10}','15778475303')
#匹配邮箱
#字母数字@地址.com
print(re.findall(r'[a-zA-Z0-9]+@[a-zA-Z0-9_-]+[.][a-zA-Z0-9_-]+$','747477910@qq.com'))
#['747477910@qq.com']
print(re.findall(r'[a-zA-Z0-9]+@[a-zA-Z0-9_-]+[.][a-zA-Z0-9_-]+$','LkwNaruto@163.com'))
txt = 'lkwnaruto@163.com'
res = re.findall(r'\w+@163[.]\w+',txt)
print(res)
练习题1:扩展:电话号中间4位变成*
sub的第一个参数是被替换的内容规则,第二个参数是替换的内容 ,第三个是替换的字符串对象。
练习题2:ls= ['123我','_咋hello','这php','么','不帅789','呢???']
需求:匹配输出“我咋这么帅呢”
练习题3:把域名替换成https://localhost/
img = (
['<img src="http://www.baidu.com/a.jpg" width="250" height="100" />'],
['<img src="http://www.taobao.com/b.jpg" width="250" height="100" />'],
['<img src="http://www.zijie.com/c.jpg" width="250" height="100" />']
)