正则是我们编程中用到的用来匹配字符串,相信大家都不陌生,其实正则只需要从基础只是开始学起,掌握了这些东西对于复杂的东西做起来才能得心应手。

python中的正则匹配需要导入模块,并且我们先介绍一下re.match()方法:

语法:

    result = re.match(RegExp,string) 

    RegExp: 代表需要匹配的正则

    string: 表示需要匹配的字符串

    result:返回匹配的结果

    match():从string的头部开始匹配

    pipei_str = result.group():通过group()接收匹配结果

匹配单个字符:

# . 匹配任意1个字符(除了\n)
# [ ]  匹配[ ]中列举的字符
# \d   匹配数字,即0-9
# \D   匹配非数字,即不是数字
# \s   匹配空白,即 空格,tab键
# \S   匹配非空白
# \w   匹配单词字符,即a-z、A-Z、0-9、_
# \W   匹配非单词字符
import re

# 根据正则表达式从头匹配指定的字符串数据
# 1. pattern: 正则表达式
# 2. string: 要匹配的字符串
# .: 匹配任意一个字符除了\n
match_obj = re.match("t.o", "t\no")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# []:匹配列举中任意一个字符
match_obj = re.match("葫芦娃[12]", "葫芦娃12")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配银行卡密码其中一位,范围:0-9
match_obj = re.match("[0-9]", "6")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# \d=>[0-9]匹配0-9中的任意一个数据
match_obj = re.match("\d", "6")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# \D:匹配非数字的字符
match_obj = re.match("\D", "f")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# \s:匹配空白字符
match_obj = re.match("葫芦娃\s[12]", "葫芦娃\t1")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# \S:匹配非空白字符
match_obj = re.match("葫芦娃\S[12]", "葫芦娃&1")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配网站上某一位密码,密码是由字母,数字,下划线
match_obj = re.match("[a-zA-Z0-9_]", "_")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")
# \w:字母,数字,下划线, 提示:还包含汉字
match_obj = re.match("\w", "哈")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# \W:匹配是非数字,非字母,非下划线的字符
match_obj = re.match("\W", "%")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

匹配结果:

匹配失败
葫芦娃1
6
6
f
葫芦娃    1
葫芦娃&1
_
哈
%

匹配多个字符:

# *    匹配前一个字符出现0次或者无限次,即可有可无
# +    匹配前一个字符出现1次或者无限次,即至少有1次
# ?    匹配前一个字符出现1次或者0次,即要么有1次,要么没有
# {m}  匹配前一个字符出现m次
# {m,n}匹配前一个字符出现从m到n次



代码:

import re

# *匹配的是前一个任意字符可能出现0次或者多次
match_obj = re.match("t.*o", "to")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# +匹配前一个任意字符至少出现1次
match_obj = re.match("t.+o", "twsdfasdfo")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# ?匹配前一个字符出现1次或者0次
match_obj = re.match("https?", "http")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配前一个字符出现m次
match_obj = re.match("ht{2}p", "htttp")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# {m,n}匹配前一个字符出现从m到n次
match_obj = re.match("to{1,2}", "tooo")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")
# 扩展--
# {m,}: 至少m次
match_obj = re.match("to{1,}", "tooo")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

匹配结果:

to twsdfasdfo http 匹配失败 too tooo

匹配开头和结尾:

# ^    匹配字符串开头
# $    匹配字符串结尾

代码:

import re

# 匹配以数字开头的数据
match_obj = re.match("^\d.*", "ssdf")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配以数字结尾
match_obj = re.match(".*\d$", "ssdf4")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配以数字开头中间内容不管以数字结尾
match_obj = re.match("^\d.*\d$", "4ssdf4")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")


# 匹配以数字开头中间内容不管以数字结尾, 结尾不要4或者7
# ^: 以字符串开头
# [^47]:除了指定字符以外都匹配
match_obj = re.match("^\d.*[^47]$", "4ssdfa")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

匹配结果:

匹配失败
ssdf4
4ssdf4
4ssdfa

匹配分组:

# |            匹配左右任意一个表达式
# (ab)         将括号中字符作为一个分组
# \num         引用分组num匹配到的字符串
# (?P<name>)   分组起别名
# (?P=name)    引用别名为name分组匹配到的字符串

代码:

import re

# 水果列表
fruit_list = ["apple", "banana", "orange", "pear"]

# 遍历数据
for value in fruit_list:
    # |    匹配左右任意一个表达式
    match_obj = re.match("apple|pear", value)
    if match_obj:
        print("%s是我想要的" % match_obj.group())
    else:
        print("%s不是我要的" % value)

# 匹配邮箱: 163,126,qq,sina,yahoo
# (ab) 将括号中字符作为一个分组
match_obj = re.match("[a-zA-Z0-9_]{4,20}@(163|126|qq|sina|yahoo)\.com", "hello@163.com")
if match_obj:
    print(match_obj.group())
    # 获取分组数据
    print(match_obj.group(1))
else:
    print("匹配失败")

# qq:10888
match_obj = re.match("(qq):([1-9]\d{4,10})", "qq:10888")

if match_obj:
    print(match_obj.group())
    # 分组:默认是1一个分组,多个分组从左到右依次加1
    print(match_obj.group(1))
    print(match_obj.group(2))
else:
    print("匹配失败")

# <html>hh</html>
match_obj = re.match("<[a-zA-Z1-6]+>.*</[a-zA-Z1-6]+>", "<html>hh</div>")

if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("<([a-zA-Z1-6]+)>.*</\\1>", "<html>hh</html>")

if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# <html><h1>www.baidu.com</h1></html>
# \num:引用分组匹配的数据
match_obj = re.match("<([a-zA-Z1-6]+)><([a-zA-Z1-6]+)>.*</\\2></\\1>", "<html><h1>www.baidu.com</h1></html>")

if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# (?P<name>)   分组起别名
# (?P=name)    引用别名为name分组匹配到的字符串,这个太麻烦,反正用的少

match_obj = re.match("<(?P<name1>[a-zA-Z1-6]+)><(?P<name2>[a-zA-Z1-6]+)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.baidu.com</h1></html>")

if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

匹配结果:

apple是我想要的
banana不是我要的
orange不是我要的
pear是我想要的
hello@163.com
163
qq:10888
qq
10888
<html>hh</div>
<html>hh</html>
<html><h1>www.baidu.com</h1></html>
<html><h1>www.baidu.com</h1></html>

r的作用:

# r的作用:表示使用是原始字符串数据,数据里面的反斜杠不需要进行转义,一个反斜杠就是一个正真的反斜杠

import re

my_str = "c:\\a\\b\\c"
print(my_str)

# match_obj = re.match("c:\\\\a\\\\b\\\\c", my_str)
# if match_obj:
#     print(match_obj.group())
# else:
#     print("匹配失败")

# r的表示使用是原始数据,数据里面的反斜杠不需要进行转义,针对的只是反斜杠

# 建议: 如果使用使用正则表达式匹配数据可以都加上r,要注意r针对的只是反斜杠起作用,不需要对其进行转义
match_obj = re.match(r"c:\\a\\b\\c", my_str)
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match(r"a\.w", "a.w")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

执行结果:

c:\a\b\c
c:\a\b\c
a.w


正则表达式对象的常用方法

    1. re.findall(s,start, end):

      返回一个列表,如果正则表达式中没有分组,则列表中包含的是所有匹配的内容,

      如果正则表达式中有分组,则列表中的每个元素是一个元组,元组中包含子分组中匹配到的内容,但是没有返回整个正则表达式匹配的内容


    2. re.finditer(s, start, end):

      返回一个可迭代对象

      对可迭代对象进行迭代,每一次返回一个匹配对象,可以调用匹配对象的group()方法查看指定组匹配到的内容,0表示整个正则表达式匹配到的内容


    3. re.search(s, start, end):

      返回一个匹配对象,倘若没匹配到,就返回None

      search方法只匹配一次就停止,不会继续往后匹配


    4. re.match(s, start, end):

      如果正则表达式在字符串的起始处匹配,就返回一个匹配对象,否则返回None


    5. re.sub(x, s, m):

      返回一个字符串。每一个匹配的地方用x进行替换,返回替换后的字符串,如果指定m,则最多替换m次。对于x可以使用/i或者/g<id>id可以是组名或者编号来引用捕获到的内容。

      模块方法re.sub(r, x, s, m)中的x可以使用一个函数。此时我们就可以对捕获到的内容推过这个函数进行处理后再替换匹配到的文本。


    6. re.split(s, m):分割字符串

      返回一个列表

      用正则表达式匹配到的内容对字符串进行分割

      如果正则表达式中存在分组,则把分组匹配到的内容放在列表中每两个分割的中间作为列表的一部分,如:

rx = re.compile(r"(\d)[a-z]+(\d)") 
      s = "ab12dk3klj8jk9jks5" 
      result = rx.split(s) 
      返回['ab1', '2', '3', 'klj', '8', '9', 'jks5']



总结:

    1. 对于正则表达式的匹配功能,Python没有返回true和false的方法,但可以通过对match或者search方法的返回值是否是None来判断

    2. 对于正则表达式的搜索功能,如果只搜索一次可以使用search或者match方法返回的匹配对象得到,对于搜索多次可以使用finditer方法返回的可迭代对象来迭代访问

    3. 对于正则表达式的替换功能,可以使用正则表达式对象的sub或者subn方法来实现,也可以通过re模块方法sub或者subn来实现,区别在于模块的sub方法的替换文本可以使用一个函数来生成

    4. 对于正则表达式的分割功能,可以使用正则表达式对象的split方法,需要注意如果正则表达式对象有分组的话,分组捕获的内容也会放到返回的列表中