4 Python中使用正则表达式

4.1 RE模块简述

 正则表达式(RE)是指高级文本匹配模式。在正则表达式中,有两个非常关键的术语:搜索和匹配。

4.1.1 正则表达式的匹配规则

首先先了解一下re.search()和re.match()函数

  • re.search(pattern, string, flags=0):用于扫描整个字符串并返回第一个成功匹配的字符串。其中,pattern参数用于传入需要匹配的正则表达式;string参数用于传入要匹配的字符串;flags参数用于标记、控制正则表达式的匹配方式。flags = re.I表示不区分大小写;flags = re.S表示可以匹配任意字符,包括换行符。若匹配成功,则re.rearch()函数返回一个匹配对象,否则返回None。
  • re.match(pattern, string, flags=0):尝试从字符串的起始位置匹配一个模式(匹配到首位符合模式的字符就返回不会管后面的字符,首位字符不符合就失败了),如果起始位置匹配失败,则返回None。参数含义与re.rearch()类似。若匹配成功,re.match()函数就会返回一个匹配对象,否则返回None。(在match()函数下还有一些方法,比如:group()、groups()、start()->>>匹配字符的起始位置、end()->>>匹配字符的结束位置、span()->>>匹配字符的起始和结束位置、string->>>返回匹配的字符串。都是re.match().group()/start()/string这种方式)

同时,可以使用group(num)或groups()匹配对象方法获取匹配表达式,其被称为“匹配对象的方法”,具体作用如此下:

  • group(num=0):返回全部的匹配对象或者指定编号是num的子组(比如这里就是指定编号为0的子组)
  • groups():返回一个元组,它包含了所有子组。若匹配失败,则返回一个空元组。
import re
#-------------match()
str = 'abcdab'
pattern = 'ab'  # 首先可以暂时把pattern看成字符串,不看作是正则表达式
res = re.match(pattern, str)  # 只有在首位匹配上了就会成功并且返回
print(res)  # 结果为:<re.Match object; span=(0, 2), match='ab'>
str_1 = 'cdabab'
print(re.match(pattern, str_1))  # 当首位没有匹配到,就会返回None
print(res.group())  # 结果为:ab,出现一次就记录,不会重复
print(re.search(pattern, str_1))  # 结果为:<re.Match object; span=(2, 4), match='ab'>,直到找到第一个出现符合的字符并返回
print(re.findall(pattern, str))  # 结果为:['ab', 'ab'],出现多少次记录多少次

在使用正则表达式时还会使用一些常用的函数

常用的函数解释
compile(pattern,flags=0)对传入的正则表达式pattern进行编译,flags是可选标识符,返回一个regex对象(用正则表达式编译后成为regex对象)
search(pattern, string, flags=0)在字符串string中搜索正则表达式模式pattern第一次出现的位置,lags是可选标识符。若匹配成功,则返回一个匹配对象,否则返回None
match(pattern, string, flags=0)尝试用正则表达式pattern匹配字符串string,flags是可选标识符。若匹配成功,则返回一个匹配对象,否则返回None
findall(pattern, string)^a在字符串string中搜索正则表达式模式pattern所有出现(不计重复)的位置,返回所有匹配对象构成的列表
finditer(pattern, string)^b与findall()类似,只是finditer()返回的是迭代器而不是列表。对于每个匹配,这个迭代器返回一个匹配对象
split(pattern, string, max=0)

根据正则表达式模式pattern中的分隔符把字符串string分隔为一个列表,返回最后匹配成功的列表,共分隔max次

sub(pattern, repl, string, max=0)把字符串string中所有匹配正则表达式模式pattern的地方替换成字符串repl,若没有给出max的值,则对所有匹配的地方进行替换

注意:compile()函数的编译功能类似C++的编译功能。使用compile()函数后只编译一趟,不使用则会多次编译,而多次编译浪费CPU资源和内存空间。既然正则表达式的编译是必需的,索性就用compile()函数编译好!

import re
content = '''<title>this is python</title>'''
# compile(pattern,flags=0)编译,一般用于同一个正则表达式被调用多次
result = re.compile(r'<title>([\w\W]*)</title>')  # compile()编译后返回一个正则表达式对象result,它可以直接使用match()等函数
print(result.match(content))  # 结果为:<re.Match object; span=(0, 29), match='<title>this is python</title>'>
# flags参数
re.compile('', flags=re.I)  # 不区分大小写
re.compile('', flags=re.S)  # 点的任意匹配模式,改变'.'的行为
re.compile('', flags=re.L)  # 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
re.compile('', flags=re.M)  # 多行模式,改变'^'和'$'的行为
re.compile('', flags=re.X)  # 不详细模式,这个模式下正则表达式时多行,忽略空白符,并可以加入注释
re.compile('', flags=re.U)  # 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性

4.1.2 正则表达式(RE)模块使用的符号

正如上面说的,两个关键术语:搜索和匹配。在正则表达式这一“匹配模式”中,依照这两个关键字,分成了两种方式:也就是搜索和匹配。

  • 搜索:在一个字符串中匹配出其中的一个字符串。其实在C语言和Java中都接触过相关的匹配方法;
  • 匹配:是指判断一个字符串能否从指定的起始处求全部或部分地匹配一个给定的字符串。

正则表达式使用了一些字符,如*(星号)、?(问号)等来匹配相应的结果,这些字符被称为“元字符”。下面给出一些常见的元字符。

字符解释
literal用于表示需要匹配的任意字符,这里以literal为例
a1|a2管道符“|”用于匹配两个任意字符中的一个,这里会匹配a1或者a2两个字符串中的一个
.需要匹配除换行以外的某一个字符
^需要匹配某一个字符串时,用于标注它的起始位置
$需要匹配某一个字符串时,用于标注它的结尾位置
*匹配*前面一个字符0次或者全部出现的结果
+匹配+前面一个字符1次或者全部出现的结果
?匹配?前面一个字符0次或者1次出现的结果
{N}按照大括号里标注的次数(这里是N次)匹配大括号前面的一个字符
{M,N}按照大括号里标注的次数(这里是M~N次)匹配大括号前面的一个字符
[abc]匹配中括号里出现的任意一个字符
[a-z]匹配规定范围内的字符,这里是a~z,即匹配所有的小写字母
[A-Z]匹配规定范围内的字符,这里是A-Z,即匹配所有的大写字母
[A-z]匹配规定范围内的字符,这里是A-z,即匹配A-z的字母,即大写和小写字母
[^a-z]不匹配规定范围内的字符,这里是a~z,即不匹配所有的小写字母
.*?[a-z]匹配中括号里出现的所有字符串,这里是匹配一段给定字符串中所有的小写字母
()用小括号括住的内容为一个子组,类似四则运算中的用途(我理解的是优先级,先做罗括号内的)

正则表达式还包含一些特殊字符,类似ASCII码中定义的转义字符,比如\n表示换行符、\t表示制表符、\a用于使蜂鸣器鸣叫,还有一些如下表(单字符匹配,都是匹配第一个位置上的字符)

字符解释
\d匹配任意数字、作用和[0-9]一样
\w匹配任意大小写字母、数字和下划线,其反义字符是\W(就是相反,不匹配匹配任意大小写字母、数字和下划线)
\s匹配任意空白字符,其反义字符是\S
\b匹配单词的边界,其反义字符是\B
\nn匹配原先保存的子组
\c逐一匹配“\”后的字符,这里是匹配“\”后的字母c
\A匹配字符串的起始
\Z匹配字符串的结尾
import re
# ------------------元字符-----------------
# .表示任意1个字符,除了\n
print(re.match('.', '$skhaiq'))  # 结果为:<re.Match object; span=(0, 1), match='$'>
print(re.match('.', '\n'))  # 结果为:None
print(re.match('.', '''
'''))  # 结果为:None
print(re.match('.', '\t'))  # 结果为:<re.Match object; span=(0, 1), match='\t'>
# \d 表示0-9之间的任意一个数字
print(re.match('\d', '$skhaiq'))  # 结果为:None
print(re.match('\d', '1$2skhaiq'))  # 结果为:<re.Match object; span=(0, 1), match='1'>
# \D 除了0-9之外的其他字符
print(re.match('\D', '$skhaiq'))  # 结果为:<re.Match object; span=(0, 1), match='$'>
# \s 表示空白字符
print(re.match('\s', ' $skhaiq'))  # 结果为:<re.Match object; span=(0, 1), match=' '>
print(re.match('\s', '\n'))  # 结果为:<re.Match object; span=(0, 1), match='\n'>
print(re.match('\s', '\t'))  # 结果为:<re.Match object; span=(0, 1), match='\t'>
# \S 表示非空白字符
print(re.match('\S', '\n'))  # 结果为:None
print(re.match('\S', '\\'))  # 结果为:<re.Match object; span=(0, 1), match='\\'>
# \w 大小写字母、数字、下划线
print(re.match('\w', '\\'))  # 结果为:None
print(re.match('\w', '_'))  # 结果为:<re.Match object; span=(0, 1), match='_'>
print(re.match('\w', 'a'))  # 结果为:<re.Match object; span=(0, 1), match='a'>
# \W 除了大小写字母、数字、下划线之外的字符
print(re.match('\W', '\\'))  # 结果为:<re.Match object; span=(0, 1), match='\\'>
print(re.match('\W', 'a'))  # 结果为:None
# 字符集[]->>>表示匹配[]出现的任意一个字符
print(re.match('[abcd]', 'ab'))  # 结果为:<re.Match object; span=(0, 1), match='a'>
print(re.match('[abcd]', 'za'))  # 结果为:None,因为match()只看首位符不符合
print(re.findall('[abcd]', 'za'))  # 结果为:['a']
print(re.match('[a-d]', 'a'))  # 结果为:<re.Match object; span=(0, 1), match='a'>
print(re.match('[0-9]', '1a'))  # 结果为:<re.Match object; span=(0, 1), match='1'>
print(re.match('[0-9a-zA-Z]', 'akj45'))  # 结果为:<re.Match object; span=(0, 1), match='a'>
# 多个单字符同时匹配
print(re.match('[0-9][a-z]', '5a'))  # 结果为:<re.Match object; span=(0, 2), match='5a'>
print(re.match('\w\w', '5a'))  # 结果为:<re.Match object; span=(0, 2), match='5a'>
# 取反[^0-9]->>>除了中括号内的都可以匹配
print(re.match('[^0-9]', 'a1c'))  # 结果为:<re.Match object; span=(0, 1), match='a'>
# ------------------转义字符-----------------
str1 = "D:\\py_works\ne\test.py"  # \n和\t有特殊意义
print(str1)  # 结果为:e	est.py,不是预期的结果,会先用Python语法去理解这段字符串
str1_1 = "D:\\\py_works\\ne\\test.py"
print(str1_1)  # 结果为:D:\\py_works\ne\test.py,是想要的结果
str1_2 = r"D:\\py_works\ne\test.py"  # r符号可以直接转义整个字符串
print(str1_2)  # 结果为:D:\\py_works\ne\test.py
print(re.match('\d', '\d'))  # 结果为:None,前者\d是表示数字,后面\d在Python默认为路径(我们想把它当成字符串,所以前后都需要转义,默认为\\d)
print(re.match('\\d', '\d'))  # 结果为:None,前面对\d进行\转义后变成了字符串的\d,但是后面还是默认为\\d,无法匹配
print(re.match('\\\d', '\d'))  # 结果为:<re.Match object; span=(0, 2), match='\\d'>,前面第一个\对第二个\进行转义就变成了\\d,与后面默认\\d匹配上了
print(re.match('\\\\d', '\d'))  # 结果为:<re.Match object; span=(0, 2), match='\\d'>,前面第一个\对第二个\转义,第三个\对第四个\进行转义,也为\\d,与后面默认\\d匹配上了
# 优先使用Python,再使用正则表达式进行处理字符
print(re.match('\\n', '\n'))  # 结果为:<re.Match object; span=(0, 1), match='\n'>
#print(re.match('D:\\py_works\ne\test.py', 'D:\\py_works\ne\test.py'))  # 会报错
print(re.match(r'D:\\py_works\ne\test.py', 'D:\\py_works\ne\test.py'))  # 结果为:<re.Match object; span=(0, 20), match='D:\\py_works\ne\test.py'>
print(re.match('D:\\\\py_works\\ne\\test.py', 'D:\\\\py_works\\ne\\test.py'))  # 结果为:None
print(re.match('D:\\\\py_works\\\\ne\\\\test.py', 'D:\\py_works\\ne\\test.py'))  # 结果为:<re.Match object; span=(0, 22), match='D:\\py_works\\ne\\test.py'>
# ------------------元字符-----------------
# *->>>匹配*前面一个字符0次或者全部出现的结果,\d*表示:尽可能匹配多的数字(也就是贪婪模式)
print(re.match('\d*', '18645260000a1234'))  # 结果为:<re.Match object; span=(0, 11), match='18645260000'>
# +->>>匹配+前面一个字符1次或者全部出现的结果
print(re.match('\d+', '186450a1234'))  # 结果为:<re.Match object; span=(0, 6), match='186450'>
print(re.match('\d+', 'a186450a1234'))  # 结果为:None
# ?->>>匹配?前面一个字符0次或者1次出现的结果,尽可能不匹配字符(懒惰模式)
print(re.match('\d?', '186450a1234'))  # 结果为:<re.Match object; span=(0, 1), match='1'>
print(re.match('\d?', 'aaa'))  # 结果为:<re.Match object; span=(0, 0), match=''>
print(re.match('\d?', ''))  # 结果为:<re.Match object; span=(0, 0), match=''>
# {N}匹配N次、{N,}匹配>=N次以上、{M,N}匹配M~N次
print(re.match('\d{5}','186450659a1234'))  # 结果为:<re.Match object; span=(0, 5), match='18645'>
print(re.match('\d{5,}','186450659a1234'))  # 结果为:<re.Match object; span=(0, 9), match='186450659'>
print(re.match('\d{5,8}','186450659a1234'))  # 结果为:<re.Match object; span=(0, 8), match='18645065'>

边界处理(^和$)和单词边界(\b)、非边界和(\B):

^表示:用于标注它的起始位置

$表示:用于标注它的结尾位置

注意:单词边界\b与\s的区别,不能使用\b来查找空格!(我试了会匹配不出来的!)只能用\s来匹配空格

import re
# 匹配一个电话号码
tel = '13589345346aa'
# 假设要辨别这是不是电话号码,后面有字母肯定不是,但利用普通的从左到右匹配,会认为是。那么就可以用到边界处理^和$
# 电话号码的规则:第一位是1开头的,第二位比如说有3、5、8,第三位有5、6、7、8,然后再加上后面八位
# 正则表达式为:[1][358][56789]\d{8}
print(re.match('1[358][5-9]\d{8}', tel))  # 结果为:<re.Match object; span=(0, 11), match='13589345346'>
# 加上边界符号^和$
print(re.match('^1[358][5-9]\d{8}$', tel))  # 结果为:None
# 单词边界
str2 = 'I put a lighted match to the letter edward and watched it burn'
print(re.findall('ed', str2))  # 结果为:['ed', 'ed', 'ed']
# 只想找以ed结尾的
print(re.findall('ed\b', str2))  # 结果为:[],也就是没找到,因为\b没有转义
print(re.findall('ed\\b', str2))  # 结果为:['ed', 'ed']
# 只想找以ed开头的
print(re.findall('\\bed', str2))  # 结果为:['ed']
# 利用\B找不是以ed开头的单词也就是找以ed结尾的
print(re.findall('\\Bed', str2))  # 结果为:['ed', 'ed']

分组处理

# 匹配日期
t = "2022-11-36"
print(re.match('2022-11-16', '2022-11-16'))
print(re.match('\d{4}-\d{2}-\d{2}', t))  # 成功,暴露了一个问题,一个日期怎么会有34日
print(re.match('\d{4}-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', t))  # 结果为:None
print(re.match('\d{4}-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(0))  # 结果为:2022-11-24
print(re.match('\d{4}-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(1))  # 结果为:11
print(re.match('\d{4}-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(2))  # 结果为:24
#print(re.match('\d{4}-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(3)) 会报错
# 但是取不到2022,把\d{4}加上小括号,这就可以实现分组匹配
print(re.match('(\d{4})-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(0))  # 结果为:2022-11-24
print(re.match('(\d{4})-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(1))  # 结果为:2022
print(re.match('(\d{4})-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(2))  # 结果为:11
print(re.match('(\d{4})-(0[0-9]|1[0-2])-([0-2]\d|[3][0-1])', '2022-11-24').group(3))  # 结果为:24
# 分组匹配实例2
con = '''<title>this is python</title>'''
print(re.match(r'<title>([\w\W]*)</title>', con).group(1))  # 结果为:this is python 就可以采集到HTML标签内的内容
print(re.match('</?[^>]+>([\w\W]*)</?[^>]+>', con).group(1))  # 与上面等价,group()内不能填2
# 给</?[^>]+>加上小括号就可以实现分组(爬虫的清洗数据)
print(re.match('(</?[^>]+>)([\w\W]*)(</?[^>]+>)', con).group(0))  # 结果为:<title>this is python</title>
print(re.match('(</?[^>]+>)([\w\W]*)(</?[^>]+>)', con).group(1))  # 结果为:<title>
print(re.match('(</?[^>]+>)([\w\W]*)(</?[^>]+>)', con).group(2))  # 结果为:this is python
print(re.match('(</?[^>]+>)([\w\W]*)(</?[^>]+>)', con).group(3))  # 结果为:</title>

 分组起别名:(?P<name>),后面接(</(?P=name)>),引用分组起别名!

import re
#还是上面的那个title例子
# 分组起别名(?P<name>)
con = '''<title>this is python</title>'''
print(re.match(r'</?(?P<tag>\w+)>([\w\W]*)</(?P=tag)>', con).group(0))  # 结果为:<title>this is python</title>
print(re.match(r'</?(?P<tag>\w+)>([\w\W]*)</(?P=tag)>', con).group(1))  # 结果为:title
print(re.match(r'</?(?P<tag>\w+)>([\w\W]*)</(?P=tag)>', con).group(2))  # 结果为:this is python

4.2 具体使用正则表达式

在这个部分str这个变量默认就是这段英文小短篇不变。

str='''The Gift on Life

On the very first day, God created the cow. He said to the cow, "Today I have created you! As a cow, you must go to the field with the farmer all day long. You will work all day under the sun! I will give you a life span of 50 years. The cow objected, "What? This kind of a tough life you want me to live for 50 years? Let me have 20 years, and the 30 years I'll give back to you." So God agreed.

On the second day, God created the dog. God said to the dog, "What you are supposed to do is to sit all day by the door of your house. Any people that come in, you will have to bark at them! I'll give you a life span of 20 years." The dog objected, "What? All day long to sit by the door? No way! I'll give you back my other 10 years of life!" So God agreed.

On the third day, God created the monkey. He said to the monkey, "Monkeys have to entertain people. You've got to make them laugh and do monkey tricks. I'll give you 20 years life span." The monkey objected. "What? Make them laugh? Do monkey faces and tricks? Ten years will do, and the other 10 years I'll give you back." So God agreed.

On the fourth day, God created man and said to him, "Your job is to sleep, eat, and play. You will enjoy very much in your life. All you need to do is to enjoy and do nothing. This kind of life, I'll give you a 20 year life span." The man objected. "What? Such a good life! Eat, play, sleep, do nothing? Enjoy the best and you expect me to live only for 20 years? No way, man! Why don't we make a deal? Since the cow gave you back 30 years, and the dog gave you back 10 years and the monkey gave you back 10 years, I will take them from you! That makes my life span 70 years, right?" So God agreed.

AND THAT'S WHY... In our first 20 years, we eat, sleep, play, enjoy the best and do nothing much. For the next 30 years, we work all day long, suffer and get to support the family. For the next 10 years, we entertain our grandchildren by making monkey faces and monkey tricks. And for the last 10 years, we stay at home, sit by the front door and bark at people!

''

4.2.1 匹配对象方法group()和groups()的用法

用group()匹配含有“ea”的单词(str变量默认是英文小短篇)

用groups()匹配含有“ea”的单词返回一个元组,它包含了所有子组。(findall()好像就是把groups()得到的元组,组合起来成为的列表)

import re
res = re.search('([a-zA-Z])*?(ea)([a-zA-Z])*?', str).group()
# res = re.search('\\b([a-zA-Z])*?(ea)([a-zA-Z])*?\\b', str).group()
# 如果想控制找到一个单词,默认单词前后都空格,就可以利用\b来进行控制,需要注意:使用\b时需要转义
print(res)  # 结果为:print(res)
'''
?会把贪婪模式变成懒惰模式,即在匹配(ea)之前的字母,还没有匹配到ea,
问号的作用显示不大。一旦匹配到了ea,后面的那个问号(匹配0个或1个字符)就发挥了懒惰模式,
不再匹配字符,直接返回crea,去掉问号之后就会才会出现想要的结果:created。
在正则表达式里空格表示为/s
'''
res_1 = re.search('([a-zA-Z])*?(ea)([a-zA-Z])*', str).group()
print(res_1)  # 结果为:created
res_2 = re.search('([a-zA-Z])*?(ea)([a-zA-Z])*', str).groups()
print(res_2)  # 结果为:('r', 'ea', 'd')
'''
并且通过groups()函数可以的到一个('r', 'ea', 'd')元组,我思考为什么会是只有r和d,
后来发现[a-zA-z]中只会选择最新的1个字母,所以才只有r和d(是created中ea前面的一个字母和最后created最后一个字母)
'''
# 可以使用findall()函数(返回字符串列表)或者finditer()函数(返回一个迭代器)
# findall()函数
res1 = re.findall('(' '[a-zA-Z])*(ea)([a-zA-Z]' ')*', str)
print(type(res1))
print(res1)
'''
结果为:
<class 'list'>
[('r', 'ea', 'd'), ('r', 'ea', 'd'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('r', 'ea', 'd'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('r', 'ea', 'd'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('r', 'ea', 'd'), ('', 'ea', 't'), ('y', 'ea', 'r'), ('y', 'ea', 's'), ('d', 'ea', 'l'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('', 'ea', 't'), ('y', 'ea', 's'), ('y', 'ea', 's'), ('y', 'ea', 's')]
'''
# 得到的结果都不是想要的包含ea的单词,但是列表和元组是没法使用group()函数
# 就得考虑finditer()函数,可以发现迭代器是可以使用group()函数
res2 = re.finditer('(' '[a-zA-Z])*(ea)([a-zA-Z]' ')*', str)
print(type(res2))
print(res2)
for i in res2:
    print(i.group())
'''
结果为:
<class 'callable_iterator'>
<callable_iterator object at 0x00000226803D7C70>
created
created
years
years
years
years
created
years
years
created
years
years
years
created
eat
year
years
deal
years
years
years
years
years
eat
years
years
years
'''
res2_1 = re.match('(T)([a-zA-Z]' ')*', str).group()
print(res2_1)  # 结果为The
  • 解释这个匹配模式'([a-zA-Z])*(ea)([a-zA-Z])*'的结果:可以利用括号把它分成三段(三个子组)。1.([a-zA-Z])*中,“()*”表示满足其之前括号里给出的条件的字符串全部长度(可以匹配0次),([a-zA-Z])表示:若干个大写或小写字母;2.(ea)表示匹配所有含有“ea”这两个连续字母的英文单词。3.([a-zA-Z])*这个类似于第一段。(书上的是写'(' '[a-zA-Z])*?(ea)([a-zA-Z]' ')*?'),后来发现有些问题,一切修改在代码的注释里面)
  • 解释这个匹配模式'(T)([a-zA-Z]' ')*'的结果:设置了以字母T开头的,所以使用match()函数只能匹配以字母T开头的内容。(T)指明匹配以T开头的内容;结尾的*是指匹配前面括号里的内容0次或多次,前面括号里的内容是([a-zA-Z]' '),即以英文字母(不区分大小写)构成的字符串,后面跟一个空格意味着由不区分大小写的英文字母构成的字符串要以空格结尾。

4.2.2 使用管道符进行匹配

管道符“|”,它在数学里表示为“或”操作,或者称为“析取”,又称为“并”操作,类似于C语言中的“||”或者Python中的“or”。

import re
str1 = 'for|from|form'
str2 = 'form|for|from'
str3 = 'from|form|for'
aimStr = 'format'
result1 = re.search(str1, aimStr).group()
result2 = re.search(str2, aimStr).group()
result3 = re.search(str3, aimStr).group()
print(result1)  # 结果为:for
print(result2)  # 结果为:form
# 在这里可以看到,由于调换了form、for和from的顺序,str1和str2搜索出来的结果也不一样,
# 因为程序找到第一个满足的条件后就不会往下找了,在C或者Java中,使用或的时候只要有一个为真就不会去判断后面的条件
print(result3)  # 结果为:form

4.2.3 使用*、+、?、{}符号实现多个条件匹配

*、+、?是常用的正则表示式符号,它们分别表示匹配字符串模式出现1次或多次、出现0次或1次、出现0次或1次的字符串。这些操作符匹配的都是其左边的符号,人们也称这种操作符为Kleene闭包操作符。{}操作符,括号内可以是单个值,表示匹配规定的出现次数,也可以是由逗号分隔的两个数字,表示匹配规定的出现次数的范围({N}和{M, N})

多个符号重叠的正则表达式例子:

正则表达式模式解释
[an]other?有4个结果:ao、aot、no、not
1[0-9]?表示匹配10~19的任意数字
[0-9]{18}|[0-9]{17}X用于匹配18位身份证号码,可以以X结尾
</?[^>]+>用于匹配所有的HTML标签
[KQRBNP][a-h][1-8]-[a-h][1-8]“长代数”记谱法的国际象棋棋谱,匹配的是每个棋子的移动步骤

4.2.4 一些特殊格式的正则表达匹配模式

 比如匹配电话号码、电子邮箱等

正则表达式模式解释
\w+\d+一串以字母或数字开头,以数字结尾的密码
[A-Za-z]\w*|[A-Za-z]_第一个字符是字母,其余字符是字母、数字或下划线
86-\d{4}-\d{8}中国苏州某座机号码,如86-0512-58****63
\w+@\w+\.com电子邮箱的一般格式

Pyzhebzthon数据分析从小白到专家_百度百科这本书上学到的知识!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头少女Emily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值