一、从一个需求出发
现在有一个Info.txt
的文本信息:
姓名 地区 身局 体重 电话
况咏蜜 北京 171 48 13651054608
王心颜 上海 169 46 13813234424
马纤羽 深圳 173 50 13744234523
乔亦菲 广州 172 52 15823423525
罗梦竹 北京 175 49 18623423421
刘诺涵 北京 170 48 18623423765
岳妮妮 深圳 177 54 18835324553
贺婉萱 深圳 174 52 18933434452
叶梓遭 上海 171 49 18042432324
杜姗姗 北京 167 49 13324523342
现在需要将个人用户信息的电话号码提取出来,根据文件读写的方法实现如下:
telephone_number = []
with open("Info.txt",'r+',encoding="UTF-8") as f:
for line in f:
print(line)
name,region,height,weight,phone = line.split()
if phone.startswith("1"):
telephone_number.append(phone)
print(telephone_number)
这里面使用的是文件读写操作和字符串方法,能够满足实际需求,但是操作效率低。
引入正则表达式字符串匹配的高效率用法:
import re
with open("Info.txt",'r+',encoding="UTF-8") as f:
telephone_number = re.findall("[0-9]{11}",f.read())
print(telephone_number)
系不系很神奇,仅仅用了两行代码实现了上面的需求,这就是正则表达式,利用高效的字符匹配方法,迅速提取满足需求的信息。在介绍Python正则表达式的使用前,先介绍一些基本或者常用的正则表达式匹配规则。
二、常用的正则表达式匹配规则
.
:默认匹配除\n之外的任意一个字符;^
:匹配以某字符开头;$
:匹配字符结尾;*
:匹配*号前的字符0次或多次+
:匹配前一个字符1次或多次?
:匹配前一个字符串1次或0次{m}
:匹配前一个字符m次{n,m}
:匹配前一个字符n到m次|
:匹配|左或|右的字符(...)
:分组匹配,比如:re.search("(abc){2}a(123|45)","abcabca123")或者匹配abcabca45
\A
:只从字符开头匹配,同^
\Z
:匹配字符串结尾,同$
\d
:匹配数字0-9\D
:匹配非数字字符\w
:匹配[A-Za-z0-9]\W
:匹配非[A-Za-z0-9]\s
:匹配空白字符,比如\t、\n、\r
至于常用的正则表达式参考:最全的常用正则表达式大全
三、Python的re匹配语法
re的匹配语法有以下几种:
re.match
:从头开始匹配re.search
:全局匹配,匹配到第一个符合条件的元素group
:字符串格式groups
:元组groupdict
:字典(分组匹配)
re.findall
:把所有匹配的字符串放到以列表中的元素返回re.split
:以匹配到的字符串当做列表分隔符re.sub
:匹配字符并替换re.fullmatch
:全部匹配,整个字符串匹配成功就返回object,否则就返回None
常用方法的介绍:
-
re.match()
方法从字符串的开头进行匹配,如果开始没有匹配到则返回None。import re # 从字符串的开头进行匹配,如果开头没有匹配到则返回None print(re.match("[0-9]+","ab123preabc123abckkk")) print(re.match("[0-9]+","123preabc123abckkk")) # <re.Match object; span=(0, 3), match='123'>
re.match(pattern,string,flags=0)
从起始位置开始根据模型去字符串中匹配指定内容,匹配单个:- pattern:正则表达式
- string:要匹配的字符串
- flags标志位:用于控制正则表达式的匹配方式
-
re.search()
方法:全局匹配,匹配到第一个符合条件的·re.Match object·对象。import re # 除\n之外的任意一个字符 print(re.search(".+","\n\n\n")) # None # 获取到的值以字符串形式输出 print(re.search(".+","trainingl")) # <re.Match object; span=(0, 9), match='trainingl'>
re.search("^alex",'alex1223\n...656alex').group()
:匹配以“alex”开头的字符串。
re.search("alex$",'alex1223\n...656alex').group()
:匹配以“alex”结尾的字符串。
以解析身份证号为例,介绍group()、groups()和groupdict()方法。id_num = "421083199811302356" re.search("[0-9]{6}",id_num).group() # '421083' # 返回元组 re.search("([0-9]{3})([0-9]{3})([0-9]{8})",id_num).groups() # ('421', '083', '19981130') # 返回字典 re.search("(?P<province>[0-9]{3})(?P<city>[0-9]{3})(?P<birthday>[0-9]{8})",id_num).groupdict() # {'province': '421', 'city': '083', 'birthday': '19981130'}
-
re.findall
:把所有匹配的字符串放到以列表中的元素返回。import re # 返回匹配到的元素列表 re.findall(".","training") # ['t', 'r', 'a', 'i', 'n', 'i', 'n', 'g'] re.findall("\D+","sgdhsj1223wgdjwk2323wdjwhj") # ['sgdhsj', 'wgdjwk', 'wdjwhj']
-
re.split
:以匹配到的字符串当做列表分隔符。import re # 以数字分割元素,返回值是列表 re.split("\d+","sgdhsj1223wgdjwk2323wdjwhj") # ['sgdhsj', 'wgdjwk', 'wdjwhj']
-
re.sub("匹配模式","替换串","匹配字符串","匹配次数count")
import re # count指定替换的次数 re.sub("abc","ABC","abcdefgabcdddabc",count=2) # 'ABCdefgABCdddabc'
-
re.fullmatch
:全部匹配,整个字符串匹配成功就返回object,否则就返回None。比较少用,因为一般如果能完整匹配到整个字符串,那么使用re就没有意义了。
模式编译再使用:
(i) 先编译,再匹配
prog = re.compile(pattern)
result = prog.match(string)
(ii)等价于:result = re.match(pattern,string)
补充:Flags标志符
- re.I:忽略大小写
- re.M:多行模式,而不是忽略换行将整个文本当做一个长字符串。
- re.S(DOTALL):改变
.
的行为,make the ‘.’ special character match any character at all ncluding a newline; without thisflag, “.” will match anything except a newline.