python's thirty-first day for me re模块

正则表达式:

  re 模块 可以读懂 你写的正则表达式,根据你写的表达式去执行任务。

  正则表达式:字符串的操作。

  使用一些规则来检测字符串是否符合我的要求  ——  表单验证

  从一段字符串中找到符合我要求的内容 ——  爬虫

  字符组:字符组代表一个字符位置上可以出现的所有内容。

    1,根据ASCII码来的,范围必须是从小到大的指向。

    2,一个字符组可以有多个范围。

字符组:[字符组]
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示。
字符分为很多类,比如数字,字母,标点等等。
假如你现在要求一个位置,’只能出现一个数字‘,那么这个位置上的字符只能是0,1,2...9这10个数之一。
字符组
 
元字符 匹配内容
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线

\s

匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符(tap)
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W 匹配非字母或数字或下划线
\D 匹配非数字
\S 匹配非空白
a|b 匹配字符a或字符b
() 匹配括号内的表达式,也表示一个组
[...] 匹配字符组中的字符
[^...]

匹配除了字符组中字符的所有字符

量词:

量词 用法说明
* 重复零次或更多次
+ 重复一次或更多次
重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

.  ^  $ :

正则 带匹配字符 匹配结果 说明
海. 海燕海娇海东 海燕海娇海东 匹配所有'海.'的字符
^海. 海燕海娇海东 海燕 只从开头匹配"海."
海.$ 海燕海娇海东 海东 只匹配结尾的"海.$"

* + ? { }:

正则 待匹配字符 匹配
结果
说明
李.? 李杰和李莲英和李二棍子

李杰
李莲
李二

 
?表示重复零次或一次,即只匹配"李"后面一个任意字符
 
李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
*表示重复零次或多次,即匹配"李"后面0或多个任意字符
李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符
李.{1,2} 李杰和李莲英和李二棍子

李杰和
李莲英
李二棍

{1,2}匹配1到2次任意字符

 

 

 

 

 

 

 

 

 

注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

正则 带匹配字符 匹配结果 说明
李.*? 李杰和李莲英和李二棍子

惰性匹配
李.+? 李杰和李莲英和李二棍子

李杰

李莲

李二

惰性匹配

字符集 [ ] [^ ]:

正则 待匹配字符 匹配
结果
说明
李[杰莲英二棍子]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

 
表示匹配"李"字后面[杰莲英二棍子]的字符任意次
 
李[^和]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

表示匹配一个不是"和"的字符任意次
[\d] 456bdha3

4
5
6
3

表示匹配任意一个数字,匹配到4个结果
[\d]+ 456bdha3

456
3

表示匹配任意个数字,匹配到2个结果

分组() 与 |(或)    [^ ]:

 身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部由数字组成,首位不能为0;如果是18位,首位不能为0,且前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:

正则 待匹配字符 匹配
结果
说明
^[1-9]\d{13,16}[0-9x]$ 110101198001017032

110101198001017032

   表示可以匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$ 1101011980010170

1101011980010170

表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170

False

现在不会匹配错误的身份证号了
()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023

110105199812067023

表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}

 

 

 

 

 

 

 

 

 

 

转义符:

  在正则表达式中,有很多有特殊意义的是元字符,比如\d和\s等,如果要在正则中匹配正常正常的'\d'而不是'数字'就需要对'\'进行转义,编程‘\\’。

  在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中‘\’也有特殊的含义,本身还需要转义。所以如果匹配一次'\d',字符串中要写成'\d',那么正则里就要写成‘\\\d’,这样就太麻烦了,这个时候我们就用到了r‘\d’这个概念,此时的正则是r'\\d'就可以了。

正则 待匹配字符 匹配
结果
说明
\d \d  False
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
\\d \d  True
转义\之后变成\\,即可匹配
"\\\\d" '\\d'  True
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
r'\\d' r'\d'  True
在字符串之前加r,让整个字符串不转义

贪婪匹配:

  在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配。

正则 待匹配字符 匹配
结果
说明
<.*>

<script>...<script>

<script>...<script>
默认为贪婪匹配模式,会匹配尽量长的字符串
<.*a?> r'\d'  

<script>
<script>

加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串

几个常用的非贪婪匹配Pattern:

*?    重复任意次,但尽可能少重复。
+?     重复1次或更多次,但尽可能少重复。
??     重复0次或1次,但尽可能少重复。
{n,m}?    重复n到m次,但尽可能少重复。
{n,}?    重复n次以上,但尽可能少重复。

.*? 的用法:

.    是任意字符
*    是取0至 无限长度
?    是非贪婪模式
合在一起就是 取尽量少的任意字符,一般不会单独写,例如:
.*?x
    :就是取前面任意长度的字符,直到一个x出现。

re模块下的常用方法:

  findall:

import re
# findall接受两个参数:正则表达式 要匹配的字符串
ret = re.findall('a','eva egon yuan')
# 一个列表数据列星的返回值:所有和这条正则匹配的结果。
print(ret)  # ['a', 'a'] 返回所有满足匹配条件的结果,放在列表里。

  search:

import re

ret = re.search('a','eva egon yuan')
if ret:
    print(ret)  # <_sre.SRE_Match object; span=(2, 3), match='a'>
    print(ret.group())  # a # 找到一个就返回,从结果对象中获取结果。
# 如果匹配到就返回一个结果对象。
# 若是没有匹配到就返回一个None.

findall 和 search 的区别:

  1,search找到一个就返回,findall是找到所有的才返回。

  2,findall是直接返回一个结果的列表,search是返回一个对象。

  match:  意味着在正则表达式中添加了一个 ^     'a' ---> '^a'

import re
ret = re.match('a','ava egon yuan')
print(ret)  # <_sre.SRE_Match object; span=(0, 1), match='a'>
print(ret.group())  # a

  1,意味着在正则表达式中添加了一个 ^ 

  2,和search一样,匹配到 返回的结果对象,没匹配到,返回None.

  3,和search一样,从结果对象中,获取值,仍然用group.

  compile: 

  1,正则表达式——> 根据规则匹配字符串。

  2,从一个字符串中找到符合规则的字符串——> python

  3,正则规则 ——编译——> python能理解的语言。

  4,多次执行,就需要多次编译,浪费时间。

  5,编译 re.compile()    可以节省时间。

import re
obj = re.compile('\d{3}')
ret = obj.search('abc123eeee')
print(ret.group())  # 123

  finditer:  返回一个迭代器可以节省空间

import re
ret = re.finditer('\d','dsfd24sdf324sf')
# 返回一个存放结果的迭代器
print(ret)  # <callable_iterator object at 0x0000016DBB712860>
# print(ret.__next__())   # <_sre.SRE_Match object; span=(4, 5), match='2'>
for i in ret:
    print(i.group())

  split:

import re
ret = re.split('[ab]','abcd') # 先按‘a’分割得到‘’和‘bcd’在分别按‘b’分割
print(ret)  # ['', '', 'cd']

  sub:

import re

ret1 = re.sub('\d','H','eva3egon4alex5')
# 若字符串后没有写次数,则默认全部替换。
print(ret1)  # evaHegonHalexH

ret2 = re.sub('\d','H','eva3egon4alex5',2)
# 替换两次
print(ret2) # evaHegonHalex5

  subn:

import re

ret1 = re.subn('\d','H','eva3egon4yuan5')
# 默认全部替换并返回一个元祖。(替换后的结果,替换了多少次)
print(ret1)  # ('evaHegonHyuanH', 3)

ret2 = re.subn('\d','H','eva3egon4yuan5',1)
# 替换一次
print(ret2) # ('evaHegon4yuan5', 1)

findall的优先级查询:

import re

ret1 = re.findall('www\.(baidu|oldboy)\.com','www.oldboy.com')
# 因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可。
print(ret1)  # ['oldboy']

# 取消findall中分组的优先权限
ret2 = re.findall('www\.(?:baidu|oldboy)\.com','www.oldboy.com')
# 在分组里的起始,加上 ?: 就可以取消findall中分组的优先权限
print(ret2) # ['www.oldboy.com']

split 的优先级查询:

import re

ret1 = re.split('\d+','eva3egon4yuan5')

print(ret1)  # ['eva', 'egon', 'yuan', '']

ret2 = re.split('(\d+)','eva3egon4yuan5')
print(ret2) # ['eva', '3', 'egon', '4', 'yuan', '5', '']

# 在匹配部分加上()之后所切出的结构是不同的。
# 没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项。
# 这个在某些需要保留部分的使用过程是非常重要的。

匹配标签:

import re

ret = re.search('<(?P<tag_name>\w+)>\w+</(?P=tag_name)>','<h1>hello</h1>')
# 还可以在分组中利用?<name>的形式给分组起名字
# 获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))    # h1
print(ret.group())  # <h1>hello</h1>

# 如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致。
# 获取的匹配结果可以直接用group(序号)拿到对应的值
ret = re.search(r'<(\w+)>\w+</\1>','<h1>hello</h1>')
print(ret)  # <_sre.SRE_Match object; span=(0, 14), match='<h1>hello</h1>'>
print(ret.group(0)) # <h1>hello</h1>
print(ret.group(1)) # h1
print(ret.group())  # <h1>hello</h1> 默认是 0

猜你喜欢

转载自www.cnblogs.com/stfei/p/8968098.html
今日推荐