正则表达式

什么是“正则表达式”

“正则表达式”是一组由字母和符号组成的特殊文本,可以帮助我们从某个复杂的字符串中,提取出满足我们要求的特殊文本。

用一个比喻理解**“正则匹配的过程”**:苹果道具相当于写的“正则表达式”,水果市场相当于“字符串”,“正则匹配的过程”就像拿着苹果道具去“水果市场”找苹果的过程,每匹配到一个就返回一个,否则就什么都没有。

常用“操作符”

正则表达式有很多专用的操作符(有称“元字符”)、特殊字符和修饰符。

“元字符”指的是那些不仅仅可以表示字符本身含义、并且还可以表示其他特殊含义的字符。常用的元字符有. [ ] ( ) ^ $ | \ ? * + { }共11种,为了方便记忆和学习,将元字符细化为7个普通元字符+4个常用量化符。

特殊字符主要介绍6个,\d、 \D、 \s、 \S、 \w、 \W

修饰符主要介绍3个,re.I、 re.M、 re.S

  1. 7个普通元字符
普通元字符说明
.点号,可以匹配(除了换行符以外的)任意单个字符
[ ]方括号,可以匹配括号内的任意字符,括号中的每个字符是or的含义
( )组,开匹配括号内的表达式,括号中的每个字符是and的含义
^乘方符号,表示以…开头
$美元符号,表示以…结尾
|或运算符,用于匹配符号前或符号后的字符
\转义字符,可以让某些字母表示特殊含义
  1. 4个常用量化符

“量化符”指的是将紧挨着量化符前面的那个字符,匹配0次、1次或者多次。

量化符说明
?前面紧挨的元素,最多匹配一次0<=x<=1
*前面紧挨的元素,匹配0次或多次x>=0
+前面紧挨的元素,匹配1次或多次x>=1
{n}前面紧挨的元素,正好匹配n次x=n
{n,}前面紧挨的元素,至少匹配n次x>=n
{n,m}前面紧挨的元素,至少匹配n次,至多匹配m次n<=x<=m
  1. 6个特殊符号

“特殊符”指的是由转义符加某些字母组合而成的,具有特殊意义的特殊字符。

特殊字符说明
\d匹配一个数字字符。等价于[0-9]
\D匹配一个非数字字符。等价于[^0-9]
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]
\S匹配任何非空白字符。等价于[^\f\n\r\t\v]
\w匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W匹配任何非单词字符。等价于[^A-Za-z0-9_]
  1. 3个常用修饰符
修饰符说明
re.I使匹配对大小写不敏感
re.M多行匹配,影响^和$
re.S使. 匹配包括换行在内的所有字符

常用方法介绍

  • findall():扫描整个字符串,以列表形式返回所有的匹配值。
  • match():匹配字符串的开头,如果开头匹配不上,则返回None。
  • search():扫描整个字符串,匹配后立即返回,不在往后面匹配值。
  • compile():将字符串编译成正则表达式对象,供match() 、 search() 和findall()函数使用。
  • sub():扫描整个字符串,用于替换字符串的某些值。
  • split():扫描整个字符串,按照指定分隔符切分字符串

在Python中,在使用正则表达式之前,需要导入re模块。

import re
  1. find()
	findall(正则表达式,目标字符串)

使用findall() 之后返回的结果是一个列表,列表中是符合正则要求的字符串。

import re
s = "abc123+-"
a = re.findall('abc',s)
print(a)

输出结果

['abc']

如果我们分别只想获取字符串中的一个或者多个

import re
s = 'ab张cd三abc'
a = re.findall('a',s)
b = re.findall('[a | b]',s)
print(a)
print(b)

输出结果

['a', 'a']
['a', 'b', 'a', 'b']

可以发现:findall()函数会直接返回所有匹配对象,组成的列表,与search()函数、match()函数不同,不需要调用group()函数。

如果没有匹配上,不会报错,而是返回一个空列表

import re
s = 'ab张cd三abc'
a = re.findall('Q',s)
print(a)

输出结果

[]

看一个稍微复杂一点的案例(爬虫经常见到)

html = '''<html>
<head lang="en">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
   <div id="content">
       <ul id="ul1">
           <li>first</li>
           <li>second</li>
           <li>third</li>
       </ul>
       <ul id="ul2">
           <li>alpha</li>
           <li>beta</li>
       </ul>
    </div>
    <div id="url">
        <a href="http:www.baidu.com" title="baidu">baidu</a>
        <a href="http:www.tipdm.com" title="tipdm">tipdm</a>
    </div>
</body>
</html>
'''

如果想要使用正则表达式,获取其中li标签,或者获取其中href属性,应该怎么做?

# 获取li标签
re.findall('<li>(.*?)</li>',html)

# 获取href属性
re.findall('<a href="(.*?)" ',html)

结果如下:

['first','second','third','alpha','beta']

['http:www.baidu.com','http:www.tipdm.com']

操作很简单,固定写法:首尾照抄字符串源代码,想要的东西使用()小括号,括起来里面写 .*?

这里 .*?表示非贪婪匹配,.*表示贪婪匹配。

  • . 可以匹配除了换行符以外的所有字符;
  • * 表示匹配前面的字符无限次;
  • ? 前面紧挨的元素,最多匹配一次;

用一个例子简单说明:

import re
s = 'a123b456b789b3'
a = re.findall('a(.*)3',s)
b = re.findall('a(.*?)3',s)
print(a)
print(b)

结果如下

['123b456b789b']
['12']

它们的区别在于:贪婪匹配是尽可能多的匹配内容,非贪婪匹配是尽可能少的匹配内容。字符串s中有两个3,贪婪匹配会一直匹配到最后一个3,但是非贪婪匹配找到第一个3后,就停止了。

  1. match()
	match(正则表达式,目标字符串)

用法演示:

s = 'ab张cd三abc'
a = re.match('a',s)
print(a)

结果如下:

<re.Match object; span=(0, 1), match='a'>

可以发现:这里得到的是一个match对象,并没有任何的结果。那么,怎么获取到具体的值。
直接调用对象的group()函数,可以获取到具体的值。

s = 'ab张cd三abc'
a = re.match('a',s)
print(a.group())

结果如下:

a

如需匹配s中的b,该如何做?

s = 'ab张cd三abc'
a = re.match('b',s)
print(a.group())

结果是:

AttributeError: 'NoneType' object has no attribute 'group'

此时可以发现:报错了。这是由于match()函数只能从字符串开头匹配,如果开头没有匹配上,则会报错。因为字符串s是以a开头,不是以b开头,所以匹配不上。

注:这个函数局限性太大,用的不是太多。

  1. search()
   search(正则表达式,目标字符串)

用法与match()函数一样,相同点在于一旦匹配上了,就立即返回结果,而不再往后面匹配(即使后面能匹配上)。如果都匹配不上,会出现同样的错误:

AttributeError: 'NoneType' object has no attribute 'group'

与之不同的是,search()函数是扫描整个字符串,只要能匹配上,就有结果。match()函数如果开头匹配不上,就无法匹配。

s = 'ab张cd三abc'
a = re.search('b',s)
print(a.group())

结果是:

b
  1. compile()
    compile函数将字符串编译成正则表达式对象,供 match() 、 search() 和findall()函数使用。
    先定义一个正则表达式对象(Pattern对象),然后分别调用该对象的match() 、 search() 和findall()函数,这三个函数用法与它们原本用法相同。
print(type(re.compile(r'\d+')))

结果如下:

<class 're.Pattern'>

可以看到这是一个Pattern对象。

import re

s = '12one34two56three78four'
# 定义一个正则表达式对象,用于匹配至少一个数字
pattern = re.compile(r'\d+')
# 扫描整个字符串,匹配s字符串中,符合该正则表达式的字符串。(这里调用的是对象的findll()对象)。
print(pattern.findall(s))
# 从s3字符串,下标为1的位置,查找匹配值。
print(pattern.findall(s,1))
# 从s3字符串,下标为1到下标为6的位置之间,查找匹配值。
print(pattern.findall(s,1,6))

结果如下:

['12', '34', '56', '78']
['2', '34', '56', '78']
['2', '3']
  1. sub()
    sub()函数是Python正则表达式中,专门用于“替换”的函数。
	sub(正则表达式, 替换目标, 目标字符串, 最大替换次数)

案例演示说明:

import re

# '\D{3,5}'表示匹配非数字3-5次。
s = '12one34two56three78four'
# 这里没有指定最大匹配次数,因此默认会替换所有的匹配值
a = re.sub('\D{3,5}','字母',s)
# 这里指定最大匹配次数count=2,因此只会替换前2个匹配值
b = re.sub('\D{3,5}','字母',s,2)
# 如果count=3,则会替换3个匹配值
c = re.sub('\D{3,5}','字母',s,3)
print(a)
print(b)
print(c)

输出结果:

12字母34字母56字母78字母
12字母34字母56three78four
12字母34字母56字母78four
  1. split()
    split()函数是Python正则表达式中,专门用于“切分字符串”的函数。
	split(正则表达式, 待分割字符串,  最大分割次数)

演示案例,字符串s以“-”分隔符切分字符串

# '\D'表示匹配非数字
import re

# '\D'表示匹配非数字
s = '136-3456-7413'
# 这里如果不指定“最大分割次数”,则是不限次数切分
a = re.split('\D',s)
# 如果指定最大分割次数maxsplit=1,那么就只以第一个分隔符,进行切分
b = re.split('\D',s,1)

print(a)
print(b)

结果如下

['136', '3456', '7413']
['136', '3456-7413']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值