python正则表达式

正则表达式的特点和作用

给定一个正则表达式和另一个字符串,我们可以达到如下目的:

  1. 给定的字符串是否符合正则表达式的过滤逻辑(“匹配”)

  2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

特点:

  1. 灵活性,逻辑性个功能性非常强。
  2. 可以迅速的用极简单的方式达到字符串的复杂程度。
  3. 对于刚接触的人来说,比较晦涩难懂。

python中的re模块

不使用正则表达式的字符串匹配

# 不使用正则
s = '<html><body><h1>hello world</h1></body></html>'
left = s.find('<h1>')
right = s.find('</h1>')
print(s[left+4:right])

正则表达式的原理使用方式

msg = '娜扎热巴戴斯佟丽娅'
pattern = re.compile('佟丽娅')
res = pattern.match(msg)
print(res)

compile的使用

def compile(pattern, flags=0):
    "Compile a regular expression pattern, returning a Pattern object."
    return _compile(pattern, flags)

但是在re模块我们对这系列操作进行了封装使用就很方便

re.match()

def match(pattern, string, flags=0):
    """Try to apply the pattern at the start of the string, returning
    a Match object, or None if no match was found."""
    return _compile(pattern, flags).match(string)

注意:这个match和上面使用的match不是同一个函数。

使用案例

'''
match是从头开始匹配,头上没有返回None
'''
s1 = '佟丽娅娜扎热巴戴斯'
s2 = '娜扎热巴戴斯佟丽娅'
res = re.match('佟丽娅', s1)
print(res)
res = re.match('佟丽娅', s2)
print(res)

image-20220313111607239

re.search()

def search(pattern, string, flags=0):
    """Scan through string looking for a match to the pattern, returning
    a Match object, or None if no match was found."""
    return _compile(pattern, flags).search(string)

使用案例

'''
search不是从头开始匹配
匹配的是整个字符串
'''
s1 = '佟丽娅娜扎热巴戴斯'
s2 = '娜扎热巴戴斯佟丽娅'
res = re.search('佟丽娅', s1)
print(res)
res = re.search('佟丽娅', s2)
print(res)
print(res.group())  # 使用group提取到匹配的内容
print(res.span())   # 返回位置

image-20220313111551394

正则符号

符号意义
"."用于匹配除换行符\n之外的所有字符
"^"用于匹配字符串的开始,即行首
"$"用于匹配字符串的末尾(末尾如果有\n,就匹配\n之前的那个字符),即行尾
"*"用于将前面的模式匹配0次或者多次(贪婪模式,即尽可能多的匹配)
"+"用于将前面的模式匹配1次或者多次(贪婪模式)
"?"用于将前面的模式匹配0次或1次(贪婪模式)
"*?,+?,??"即函数那个面三种特殊字符的非贪婪模式(极可能少的匹配)
"{m,n}"用于将前面的模式匹配m次到n次(贪婪模式),即最小匹配m次,最大n次
"{m,n}?"上面一个的非贪婪版本
""\\""'\'是转义字符,在特殊字符前面加上\,特殊字符就失去了其所代表的含义,比如\+就仅仅代表加号+本身。
"[]"用于标示一组字符,如果^是第一个字符,则标示的是一个补集。比如[0-9]表示所有的数字,[^0-9]表示除了数字之外的字符。
"|"或者的意思
"(...)"用于匹配括号中的模式,可以再字符串中检索或者匹配我们所需要的内容。

使用实例:

'''匹配数字'''
s = '哈哈2'

res1 = re.search('[12345]', s)
res2 = re.search('[135]', s)
print(res1)
print(res2)

image-20220313114814710

s = '哈哈2d'

res1 = re.search('[0-9][a-z]', s)
res2 = re.search('[0-9][0-9]', s)
print(res1)
print(res2)

image-20220313114959930

'''提取前后是字母,中间是数字的'''
msg = 'abcd3g9dfggker98sf34f3dsv'
res = re.search('[a-z][0-9][a-z]', msg)
print(res.group())

image-20220313115126076

​ 我们发现只能匹配一个,在字符串msg的后面还有满足条件的字符串但是只展示一个。这就是search的匹配方式,只要有匹配的后面就不进行检索了。

re.findall()

findall 匹配整个字符串,找到一个继续向下找一直道字符串结尾。

'''提取前后是字母,中间是数字的'''
msg = 'abcd3g9dfggker98sf34f3dsv'
res = re.search('[a-z][0-9][a-z]', msg)
print(res.group())

res2 = re.findall('[a-z][0-9][a-z]', msg)
print(res2)

image-20220313115656925

题目升级:我要两边是一个字母中间一串数字。

'''两边是一个字母中间一串数字'''
msg = 'abcd3g9dfggker98sf34f3dsv'
res = re.findall('[a-z][0-9]+[a-z]', msg)
print(res)

image-20220313120217832

案例:QQ号的验证

'''qq号的验证'''
# 5-11 开头不为0
qq = '123965558822'
res = re.match('[1-9][0-9]{4,10}', qq)
print(res)
res = re.match('^[1-9][0-9]{4,10}$', qq)
print(res)

image-20220313120937553

为了判断整体的qq好我们需要加上^$

案例:用户名

'''用户名可以是字母或者数字,不能是数字开头,用户名长度必须是6位以上'''
username1 = '0admin'  # 首字母是数字
username2 = 'admin01'  # 满足条件
username3 = 'admin01***'  # 存在特殊字符
username4 = '*/admin01***'  # 开头存在特殊字符
usernames = [username1, username2, username3, username4]
for username in usernames:
    res = re.match('^[a-zA-Z][0-9a-zA-Z]{5,}$', username)
    print(res)

image-20220313122343627

元字符

符号实际意义
.匹配任意字符。
\A表示从字符串的最开始处匹配
\Z表示字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串。
\b匹配单词的边界也就是指单词和空格间的位置。
\B匹配非单词边界。
\d匹配数字字符,等价于[0-9]
\D匹配非数字字符,等价于[^\d]
\w匹配单词字符(英文、数字、下划线),等价于[a-zA-Z0-9_]
\W匹配非单词字符,等价于[^\w]
\s匹配空白符(包含换行符、Tab),等价于[\t\n\r\f]
\S匹配非空白字符

\b举例:'py\b’可以匹配“python”中的py,但是不能匹配“openpyxl”中的‘py’。但是相反\B可以匹配后者中的‘py’不能匹配前者中的‘py’。

举例:

msg = 'a.py ab.txt bb.py kk.png uu.jpg d7.py'
res = re.findall(r'\w*\.py\b',msg)
print(res)

image-20220313154313657

py前面的.有通配的意思,所以需要进行转义让他仅仅由点的意思。

案例手机号正则:

re.match('^1[35789]\d{9}$',phone)

案例:匹配数字0-100:

re.match(r'[1-9]?\d?$|100$',number)

验证输入邮箱:

'''验证输入邮箱 163 126 qq'''
email = '12345689@qq.com'
res = re.match("^\w{5,20}@(163|126|qq).com$", email)
print(res)

此案例中重点是@后面的123、126、qq或的关系

上面案例中0-100中的或不是文本的或,是整体上直接换了一批。

案例:电话号码的匹配(区号,固话号分别提取)

'''电话号'''
telephone = '010-12345678  120-98765432'
res = re.match(r'(\d{3,4})-(\d{8})\b', telephone)
print(res)
# 分别提取  需要配合小括号使用
print(res.group())
print(res.group(1))
print(res.group(2))

image-20220313184600871

案例:标签中的内容

'''标签中的内容'''
msg1 = '<html>abc</html>'
msg2 = '<h1>hello world</h1>'
msg3 = '<html><h1>hello world</h1>'
res = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>$', msg1)
print(res)
print(res.group(1))
res = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>$', msg2)
print(res)
print(res.group(1))
res = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>$', msg3)
print(res)
print(res.group(1))

# 上面的情况甚至可以匹配'<html><h1>hello world</h1>'
# 这种不规则的字符串。
# 解决这种错误需要使用number

# \1就是前面用括号限制住的第一个括号。
res = re.match(r"<([0-9a-zA-Z]+)>(.+)</\1>$", msg2)
print(res)
print(res.group(2))

image-20220313190945555

多层加深理解
# 多层使用加深印象
msg = '<html><dir><h1>Jack</h1></dir></html>'
res = re.match(r'<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)</\3></\2></\1>',msg)
print(res)
print(res.group(1))
print(res.group(2))
print(res.group(3))
print(res.group(4))

image-20220313191604328

另一种方式:

# 另一种方式
# 起名的方式  (?P<名字>正则)    使用(?P=名字)
msg = '<html><dir><h1>Jack</h1></dir></html>'
res = re.match(
    r'<(?P<name1>[0-9a-zA-Z]+)><(?P<name2>[0-9a-zA-Z]+)><(?P<name3>[0-9a-zA-Z]+)>(.+)</(?P=name3)></(?P=name2)></(?P=name1)>',
    msg)
print(res)
print(res.group(1))
print(res.group(2))
print(res.group(3))
print(res.group(4))

小结:

分组:() --> res.group(1) 获取组中匹配内容

分组的时候可以结合|使用:

telephone = '010-12345678  120-98765432'
res = re.match(r'(\d{3,4})-(\d{8})\b', telephone)
print(res)

不需要引用分组的内容:

res = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>$', msg2)
print(res)
print(res.group(1))

引用分组匹配内容:

  1. number
# \1就是前面用括号限制住的第一个括号。
# \number表示引用第number组的数据
res = re.match(r"<([0-9a-zA-Z]+)>(.+)</\1>$", msg2)
print(res)
print(res.group(2))
  1. ?P<名字>
# 起名的方式  (?P<名字>正则)    使用(?P=名字)
msg = '<html><dir><h1>Jack</h1></dir></html>'
res = re.match(
    r'<(?P<name1>[0-9a-zA-Z]+)><(?P<name2>[0-9a-zA-Z]+)><(?P<name3>[0-9a-zA-Z]+)>(.+)</(?P=name3)></(?P=name2)></(?P=name1)>',
    msg)
print(res)

re.sub

def sub(pattern, repl, string, count=0, flags=0):
    """Return the string obtained by replacing the leftmost
    non-overlapping occurrences of the pattern in string by the
    replacement repl.  repl can be either a string or a callable;
    if a string, backslash escapes in it are processed.  If it is
    a callable, it's passed the Match object and must return
    a replacement string to be used."""
    return _compile(pattern, flags).sub(repl, string, count)

替换的作用

'''re.sub'''
str1 = 'java:85,python:100'
res = re.sub(r'\d+','90',str1)
print(res)

进阶使用,(第二个参数为函数。)

'''re.sub'''


def func(temp):
    num = temp.group()
    num1 = int(num) + 1
    return str(num1)


str1 = 'java:85,python:100'
res = re.sub(r'\d+', func, str1)
print(res)

re.split()

def split(pattern, string, maxsplit=0, flags=0):
    """Split the source string by the occurrences of the pattern,
    returning a list containing the resulting substrings.  If
    capturing parentheses are used in pattern, then the text of all
    groups in the pattern are also returned as part of the resulting
    list.  If maxsplit is nonzero, at most maxsplit splits occur,
    and the remainder of the string is returned as the final element
    of the list."""
    return _compile(pattern, flags).split(string, maxsplit)

切割的作用,将切割后的内容放在列表中。

str1 = 'java:85,python:100'
res = re.split(r'[,:]',str1)
print(res)

image-20220313200411164

贪婪匹配与非贪婪匹配

python中的数量词默认是贪婪的(在少数语言中也可能默认是非贪婪的),总是尽可能匹配多的字符;非贪婪相反,总是尝试匹配尽可能少的字符。

在“*”,“?”,“+”,“{m,n}”后面加上?,是贪婪变成非贪婪。

使用案例:

str1 = '<img src="//lmg.jj20.com/up/allimg/4k/s/02/2109242332225H9-0-lp.jpg" width="1200" alt="棕榈树,海岸,蓝色大海天空,海边自然风景图片图片">'
res = re.match(r'<img src="(.*)"', str1)
print(res.group(1))
res = re.match(r'<img src="(.*?)"', str1)
print(res.group(1))

s)


[外链图片转存中...(img-fp10h4XT-1647174532066)]

### 贪婪匹配与非贪婪匹配

python中的数量词默认是贪婪的(在少数语言中也可能默认是非贪婪的),总是尽可能匹配多的字符;非贪婪相反,总是尝试匹配尽可能少的字符。

在“*”,“?”,“+”,“{m,n}”后面加上?,是贪婪变成非贪婪。

使用案例:

```python
str1 = '<img src="//lmg.jj20.com/up/allimg/4k/s/02/2109242332225H9-0-lp.jpg" width="1200" alt="棕榈树,海岸,蓝色大海天空,海边自然风景图片图片">'
res = re.match(r'<img src="(.*)"', str1)
print(res.group(1))
res = re.match(r'<img src="(.*?)"', str1)
print(res.group(1))

image-20220313202136628

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黎丶辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值