python正则表达式详解
博客主页:https://blog.csdn.net/weixin_43897615
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。可以使用事先定义好的⼀些特定字符、及这些特定字符的组合,组成⼀个“规则字符串”,这个“规则字符串”⽤来表达对字符串的⼀种过滤逻辑。
正则表达式是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。使用这个小型语言,你可以为想要匹配的相应字符串集指定规则;该字符串集可能包含英文语句、e-mail地址、TeX命令或任何你想搞定的东西。然后你可以问诸如“这个字符串匹配该模式吗?”或“在这个字符串中是否有部分匹配该模式呢?”。你也可以使用 RE 以各种方式来修改或分割字符串,现在对python中的正则进行讲解。
一、正则函数讲解
1、re.match()方法
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功,则返回none。
例子:re.match方法示例(匹配以python开头的语句)
# coding=utf-8
# 导入模块
import re
# 匹配以python开头的字符串
result = re.match("python","python.org")
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
2、re.search函数
扫描整个字符串并返回第一个成功的匹配,如果匹配成功re.search方法返回一个匹配的对象,否则返回None。
例子:re.search方法示例(匹配所有数字)
# 匹配所有数字
ret = re.search(r"\d+", "阅读次数为 9999")
ret.group()
3、re.sub函数
re.sub用于替换字符串中的匹配项。
例子:re.sub方法示例(替换空格和/)
city = re.sub(r'[/\s]', "", "/ 深圳/")
print(city)
4、findall函数
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
例子:re.sub方法示例(查找所有数字)
test_str = "9python35C++"
num = re.findall(r'\d+', test_str)
print(num)
5、re.split函数
功能:split 方法用pattern做分隔符切分字符串,分割后返回列表。如果用’(pattern)’,那么分隔符也会返回。
例子:re.split方法示例(以,分割字符)
test_str = "cat,dog,pig,panda"
animal = re.split(r'\W+', test_str)
print(animal)
6、 re.compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。如果匹配成功则返回一个Match对象。
示例:编译匹配数字的对象
pattern = re.compile(r'\d+') # 编译一个匹配数字的对象
print(pattern.match('12python34'))
print(pattern.search('12python34'))
print(pattern.findall('12python3'))
二 、python贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
非贪婪则相反,总是尝试匹配尽可能少的字符。
在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
>>> re.match(r"aa(\d+)","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
'2'
>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
'2343'
例子:爬取古诗文网古诗的标题 https://www.gushiwen.org/
titles = re.findall(r'<div\sclass="cont">.*?<b>(.*?)</b>', text, re.DOTALL)
三、原生字符串 - r
Python中字符串前面加上 r 表示原生字符串
与大多数编程语言相同,正则表达式里使用"\"作为转义字符
,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
test_str = "c:\\a\\b\\c"
ret = re.match(r"c:\\a",test_str).group()
四、正则表达式修饰符
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
例子:修饰符的作用(忽略大小写,匹配python和ruby)
test_str = "Python123RUBY"
print(re.findall(r'[a-z]+', test_str, re.I))
五、 正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
常用的正则表达式模式如下:
1、 匹配单个字符
字符 | 功能 |
---|---|
. | 匹配任意1个字符(除了\n) |
[ ] | 匹配[ ]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即 空格,tab键 |
\S | 匹配非空白 |
\w | 匹配单词字符,即a-z、A-Z、0-9、_ |
\W | 匹配非单词字符 |
2、匹配多个字符
字符 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
3 、匹配开头和结尾
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
示例:匹配163.com的邮箱地址
email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]
for email in email_list:
ret = re.match("[\w]{4,20}@163\.com$", email)
if ret:
print("%s 是符合规定的邮件地址,匹配后的结果是:%s" % (email, ret.group()))
else:
print("%s 不符合要求" % email)
4、匹配分组
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?P) | 分组起别名 |
(?P=name) | 引用别名为name分组匹配到的字符串 |
如果你想要提取子串或是想要重复提取多个字符,那么你可以选择用定义分组的形式。用()就可以表示要提取的分组(group)
示例:通过分组来匹配字符(通过分组来匹配li标签下的first item)
html = '''
<li class="item-1"><a href="link1.html">first item</a></li>
'''
ret = re.findall(r'<li\s.*?><a\s.*?>(.*?)</a></li>', html, re.DOTALL)
print(ret)