re正则表达式基础语法
表达式 | 可匹配 | 表达式 | 可匹配 |
---|---|---|---|
\r,\n | 代表回车和换行符 | ^ | 可匹配^本身 |
\t | 制表符 | $ | 匹配$符号本身 |
\ | 代表“\”本身 | . | 匹配小数点“.”本身 |
表达式 | 可匹配 |
---|---|
\d | 任意一个数字,0~9中的任意一个 |
\D | 匹配任意一个不是0-9之间的数字字符,等价于表达式[^0-9] |
\w | 任意一个字母或数字下划线,也就是A |
\W | 匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v] |
\s | 包括空格、制表符、换页符等空白字符的其中任意一个 |
\S | 匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v] |
. | 小数点可以匹配出来换行符“\n”以外的任意一个字符 |
re正则表达式基本使用方法
“.”号的基本使用
例如,下面一段文字:
苹果是绿色 香蕉是黄色 橙子是橙色 天空是蓝色
我们想要匹配与颜色相关的字符,我们可以先找出上面一段文字的共同点。
因为我们是想要匹配颜色相关的字符,而且我们还可以发现每一段文字共有“色”这一个字符,从上面的语法我们还知道“.”是可以匹配除去换行符以外的任意一个字符的。
这里最重要的一个函数就是compile()函数。该函数根据包含的正则表达式的字符串创建模式对象。可以实现更有效率的匹配。
通俗的来说就是用来写需要匹配规则的一个函数。
还有一个函数findall()是返回的是括号所匹配到的结果。
text = """苹果是绿色
香蕉是黄色
橙子是橙色
天空是蓝色
"""
p = re.compile(r".色")
print(p.findall(text))
运行结果: 这里我们将列表里的元素元素提取出来。
text = """苹果是绿色
香蕉是黄色
橙子是橙色
天空是蓝色
"""
print("提取后的结果;")
p = re.compile(r".色")
result = p.findall(text)
for i in result:
print(i)
运行结果:
“*”号的基本使用
“*”号需要重点了解一下,它的意思是匹配前面的子表达式任意次,包括0次。
比如这里“,.*” 这里就是表示匹配以中文点开头后接任意字符数量的匹配直到本行结束。
例如,我们现在匹配中文逗号往后的所有字符。
苹果,是绿色 香蕉,是黄色 橙子,是橙色 天空,是蓝色
text = """苹果,是绿色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
"""
print("提取后的结果;")
p = re.compile(r",.*")
result = p.findall(text)
for i in result:
print(i)
运行结果: 这里我门可以再次解析一下complie()函数内的表达式。
表达的意思就是我匹配的第一个字符是一个中文逗号,后面的字符可以是任意所有字符,尽可能的多的匹配不限制次数,反正就是由什么我就要什么。
“+”号的基本使用
这里我们需要知道一个加号“+”,表示匹配前面的子表达式或多次,不包括0次。
其实跟“*”号的用法大致相同。
首先我们对比一下“*”号的用法,我们想要匹配“绿色”这个字符
就比如下面这个例子:
苹果,是绿色色色 香蕉,是黄 橙子,是橙 天空,是蓝 绿
text = """苹果,是绿色色色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
绿
"""
print("提取后的结果;")
p = re.compile(r"绿色*")
result = p.findall(text)
for i in result:
print(i)
运行结果: 可以发现多出了个绿,我们要匹配的是“绿色”这样的字符啊,这就是“*”号的一个特点,匹配包含0次及以上。
那我们不想匹配这个绿呢?其实我们就可以使用“+”来进行匹配。
text = """苹果,是绿色色色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
绿
"""
print("提取后的结果;")
p = re.compile(r"绿色+")
result = p.findall(text)
for i in result:
print(i)
运行结果: 这样就剔除掉了“绿”这个字符了,因为“+”是只匹配0次以上的。
“{}”的基本使用
花括号表示前面的字符匹配指定的次数。
例如,我们还是匹配下面的“色”。
苹果,是绿色色色色色 香蕉,是黄色 橙子,是橙色 天空,是蓝色 绿
text = """苹果,是绿色色色色色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
绿
"""
print("提取后的结果;")
p = re.compile(r"色{1,3}")
result = p.findall(text)
for i in result:
print(i)
运行结果: 我们可以发现,第一个的“色”是有5个的,但是最后我们控制台上的第一个只匹配了3个,是因为在花括号里表示最少匹配1个“色”,最多匹配3个“色”。
text = """苹果,是绿色色色色色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
绿
"""
print("提取后的结果;")
p = re.compile(r"色{3}")
result = p.findall(text)
for i in result:
print(i)
运行结果: 这里表示的就是最多匹配3个“色”。
非贪婪模式
这里的非贪婪模式是用“?”来进行表示的,表示尽可能的少匹配。
例如,我们匹配下列的一些HTML标签。
<html><head><title>Title</title></head></html>
我们常规想到的肯定是这样写的:
text = """<html><head><title>Title</title></head></html>"""
print("提取后的结果;")
p = re.compile(r"<.*>")
result = p.findall(text)
for i in result:
print(i)
运行结果: 但是这里我们除了中间的Title字符没有匹配到,其他的全部都匹配到了,相当于只要符合“<.*>”表达式结果的全部都给我匹配到了,然道我们拿到后还要再做一次切割,这也太麻烦了。所以我们就需要改成非贪婪模式。
text = """<html><head><title>Title</title></head></html>"""
print("提取后的结果;")
p = re.compile(r"<.*?>")
result = p.findall(text)
for i in result:
print(i)
运行结果:
同一字符的匹配
当我们要匹配的文本出现了这种情况,需要我们匹配“.”前面的名称我们应该怎么操作呢?
苹果.是绿色色色色色 香蕉.是黄色 橙子.是橙色 天空.是蓝色 绿
这里我们就可以利用转义字符来定义了。
text = """苹果.是绿色色色色色
香蕉.是黄色
橙子.是橙色
天空.是蓝色
绿
"""
print("提取后的结果;")
p = re.compile(r".*\.")
result = p.findall(text)
for i in result:
print(i)
运行结果:
简单的实例运用
re正则表达式基础语法
首先我们回忆一下基本用法 | 表达式 | 可匹配 | |--|--| | \d | 匹配0-9之间任意一个数字字符,等价于表达式[0-9] | | \D | 匹配任意一个不是0-9之间的数字字符,等价于表达式[^0-9] | | \s | 匹配任意一个空白字符,包括 空格、tab、换行符等,等价于表达式[\t\n\r\f\v] | | \S | 匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v] | | \w | 匹配任意一个文字字符,包括大写小写字母、数字、下划线,等价于表达式[a-zA-Z0-9]缺省情况也包括Unicode文字字符,如果指定ASCII码标记,则只包括ASCII字母 | | \W | 匹配任意一个非文字字符,等价于表达式[^a-zA-Z0-9] |
匹配英文字符
例如,我们想要匹配一个英文人名应该怎么做呢?
小王 小红 Bob 小华
text = """小王
小红
Bob
小华
"""
print("提取后的结果;")
p = re.compile(r"\w*")
result = p.findall(text)
for i in result:
print(i)
运行结果: 发现并不是我们想要的结果,因为\w是匹配任意一个文字字符,但是我们要匹配的是只是英文啊,所以我们就需要用到re.A来匹配英文字符。
text = """小王
小红
Bob
小华
"""
print("提取后的结果;")
p = re.compile(r"\w*",re.A)
result = p.findall(text)
for i in result:
print(i)
运行结果: re.A它是等价于re.ASCII的两个都可以。
但是空这么多,很不美观,所以我们美化一下。
text = """小王
小红
Bob
小华
"""
print("提取后的结果;")
p = re.compile(r"\w+",re.A)
result = p.findall(text)
for i in result:
print(i)
运行结果: 改用“+”它的一些空字符就没了。
匹配手机号
例如,当我们想要匹配手机号应该怎么做呢?
小王,13258463212,11 小红,32584632571,12 小明,28525436466,13 小花,15685324624,14 小李,52698225845,15
text = """小王,13258463212,11
小红,32584632571,12
小明,28525436466,13
小花,15685324624,14
小李,52698225845,15
"""
print("提取后的结果;")
p = re.compile(r"[1-2][1-9]\d{9}")
result = p.findall(text)
for i in result:
print(i)
运行结果: 这里的中括号表示匹配第一个的1-2和第二个的1-9中的其中一个,它们个占一个位置。
其中,反斜杠也可以用在方括号里面,比如[\s,.]表示匹配:任何空白字符,或者逗号,或者点。
匹配字符串中的英文字符
例如,我们想要在数字与字母混合中提取出所有的英文字母,我们可以这样做。
a1b2c3d4e5f6g7h8i9j10l
这里我们就需要知道一个符号“^”表示非。
text = """a1b2c3d4e5f6g7h8i9j10l"""
print("提取后的结果;")
p = re.compile(r"[^\d]")
result = p.findall(text)
for i in result:
print(i)
运行结果: 这里的\d表示的是匹配数字,加上^表示的不就是非数字吗?对吧。
又比如,我们处了不匹配数字,还不匹配abc,我们可以这样写。
text = """a1b2c3d4e5f6g7h8i9j10l"""
print("提取后的结果;")
p = re.compile(r"[^\dabc]")
result = p.findall(text)
for i in result:
print(i)
运行结果:
起始、结尾,单行、多行
例如,我们想匹配水果价格前面的数字应该怎么做呢?
001-苹果价格-100 002-香蕉价格-200 003-菠萝价格-300 004-西红柿价格-400
text = """001-苹果价格-100
002-香蕉价格-200
003-菠萝价格-300
004-西红柿价格-400
"""
print("提取后的结果;")
p = re.compile(r"\d+")
result = p.findall(text)
for i in result:
print(i)
运行结果: 可以发现我们直接输入\d的时候连同后面的价格也一起匹配出来了。
那么我们可以加上一个“^”就行,表示开头位置。
text = """001-苹果价格-100
002-香蕉价格-200
003-菠萝价格-300
004-西红柿价格-400
"""
print("提取后的结果;")
p = re.compile(r"^\d+")
result = p.findall(text)
for i in result:
print(i)
运行结果: 但是它只有一行啊,我们相应匹配的是多行,这块不行,所以我们需要用到re.M它是等价于re.MULTILINE的。
text = """001-苹果价格-100
002-香蕉价格-200
003-菠萝价格-300
004-西红柿价格-400
"""
print("提取后的结果;")
p = re.compile(r"^\d+",re.M)
result = p.findall(text)
for i in result:
print(i)
运行结果: 我们匹配结尾就是用的“$”了。
text = """001-苹果价格-100
002-香蕉价格-200
003-菠萝价格-300
004-西红柿价格-400
"""
print("提取后的结果;")
p = re.compile(r"\d+$",re.MULTILINE)
result = p.findall(text)
for i in result:
print(i)
运行结果:
组选择
例如,我们想要提取前面的水果我们应该怎么操作呢?
苹果,是绿色 香蕉,是黄色 橙子,是橙色 天空,是蓝色
text = """苹果,是绿色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
"""
print("提取后的结果;")
p = re.compile(r".+,")
result = p.findall(text)
for i in result:
print(i)
运行结果: 但是我们发现,匹配后我们又出现了个“,”,但是我又不想切割。
所以我们可以用到组选择,表示当我们匹配到整个文本后,对其匹配到的结果符合这个表达式特征进行一个分组,所以就用圆括号。
text = """苹果,是绿色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
"""
print("提取后的结果;")
p = re.compile(r"(.+),")
result = p.findall(text)
for i in result:
print(i)
运行结果:
看这样就变现的去处了逗号。
那我们想要匹配多个组,多加括号就行。
text = """苹果,是绿色
香蕉,是黄色
橙子,是橙色
天空,是蓝色
"""
print("提取后的结果;")
p = re.compile(r"(.+)(,)")
result = p.findall(text)
for i in result:
print(i)
运行结果: 例如,匹配手机号和姓名。
小王,手机号13258463212 小红,手机号32584632571 小明,手机号28525436466 小花,手机号15685324624 小李,手机号52698225845
text = """小王,手机号13258463212
小红,手机号32584632571
小明,手机号28525436466
小花,手机号15685324624
小李,手机号52698225845
"""
print("提取后的结果;")
p = re.compile(r"(.+),.+([1-2][1-9]\d{9})")
result = p.findall(text)
for i in result:
print(i)
运行结果:
sub动态匹配替换
import re
text = """https://blog.csdn.net/qq_45887590/article/details/114743995"""
def subStr(match):
# Match对象的group(0) 返回的是符合表达式匹配的字符串
src = match.group(0)
# Match对象的group(1) 返回的是第一个group分组的内容
number = int(match.group(1)) + 10
dest = str(number)
# 字符串的一个替换
print(text.replace(src, dest))
# 返回值就是最终替换的字符串
return dest
# print("匹配结果:")
# p = re.compile(r"(\d+)")
# result = p.findall(text)
# for i in result:
# print(i)
newSsr = re.sub(r"(\d+)", subStr, text)
运行结果: 动态匹配成功,即使匹配多个也是相同的道理。