第十九天

re模块-正则表达式

什么是正则表达式

​ 一套规则,匹配字符串的规则

可以做什么

  1. 检测字符串是否合法--表单验证
    1. 用户输入,提前检测
    2. 提高效率,减轻服务器压力
  2. 从一个大文件中找到符合规则的内容--日志分析/爬虫
    1. 高效从一大段文字中找到符合规则的内容

正则规则

所有的规则中的字符就可以刚好匹配到字符串中的内容

元字符

字符组[abc] 一个中括号只表示一个字符的位置

匹配a 或者b 或者c

[0-9] 根据ascii码进行匹配

[A-Z] Z(91) a( 97) [a-z]

A (ASCII码) 小 a 大

#大小写 都可以 [a-zA-Z]

#数字和小写 [0-9a-z]

#数字和大小写 [0-9a-zA-Z] \w

word

#匹配一位任意数字 [0-9] \d

dight

#空白 (空格\tab\enter) (/\t/\n)

空格-->
table--> \t
enter回车--> \n

所有空格 回车 tab--> \s

表示所有空白 空格 回车


总结

元字符

[]

\d

\w

\s

\t

\n


\W 非数字字母下划线

\D 非数字

\S 非空白


[\d] \d 两个一样

[\d\D] [\s\S] [\w\W] 匹配所有

一个一个匹配

. 表示除换行符之外所有 (正常情况下)


[^] 非字符组

[^\d] 非数字的所有

[^1] 非1的所有


^ 以什么字符 开始 ^a

$ 以什么字符 结尾 a$

[ab]c ----ab 或ac

a[df]------ad 或af

a表达式|b表达式

匹配a或者b表达式中的内容

如果a成功了,不会继续和b 匹配

一般总是把长的放在左边

\ 转义符 取消特殊意义 例如 \ . 就仅仅代表一个 .

\b 匹配一个单词的开头或者结尾

​ 例如匹配 ing结尾的

eating ---------------- ing\b

() 约束 | 描述内容的范围

www\.oldboy\.com|www\.baidu\.com|www\.taobao\.com

#优化

www\.(oldboy|baidu|taobao)\.com

记忆元字符:

\d \w \s \t \n \D \W \S

[] [^] .

^ $

| ()

精准约束的时候 字符组


量词

[1235]\d 10 20 30 50 几

{n} 匹配n次

{n,} 匹配至少n次

{n,m} 至少匹配n次 至多m次

? 表示匹配0次或一次

+ 表示1次或多次

* 表示0次或多次

只约束前面一位的元字符

\d{2} 匹配两位数

\d{2,} 匹配 至少 两位数

\d{2,5} 匹配 至少 两位数 至多 5 位数

​ * 所有


0 ? 1 + (1-所有)

\d+ 整数

\d.\d+ 小数

\d+.?\d* 整数或小数

​ \d+ 前面整数

\ . ? .可出现可不出现

\d* 数字可出现 可不出现

\d+(\ .\d+) ? 整数或小数

分组的作用

手机号码 [1] [3-9]\d


贪婪匹配

.*x 表示匹配任意字符 任意多次 遇到最后一个x就停下来

\d{3,}6 到最后一个6 停止

原理:

  1. \d{3,} 先把所有的匹配完 贪婪算法
  2. 再从最后一个往回找 回溯算法

18545456665545487989666232

结果:

18545456665545487989666

非贪婪(惰性)匹配

.*?x 表示匹配任意字符 任意多次 但是一旦遇到x就停下来

\d{3,}?6

量词后面加一个 ? 尽可能少的 匹配 非贪婪

量词 \d{3,}

转义符

[().*+?] 所有内容在字符组中 会取消它的特殊含义

[a\ -c] -在字符组中 表示范围 如果不希望他表示范围 需要转义 或者放在最前面 或者最后面

18位身份证

无验证: [1-9]\d{16}[0-9X]

15位

[1-9]\d{14}

18或15

第一种:

^( [1-9]\d{16}[0-9X]|[1-9]\d{14})$

加括号表示 18位 和 15位 不能多不能少

第二种:

^( [1-9]\d{14}(\d{2}[\dX])?$

第三种:

^[1-9](\d{16}[\dX]|\d{14})

第四种:

\d{17}[\d|x]|\d{15}

导入正则模块

findall 找到所有的返回

还是按照完整的正则进行匹配,只是只显示括号里匹配的内容

search 只找一个就返回

import re

re.findall('\d','12345xxxxx')

返回一个列表
['1','2','3','4','5']


re.findall('\d+','12345xxxxx')

['12345']


ret=re.search('\d+3','12345xxxxx')
print(ret)

<_sre.SRE_Match object; span=(0, 3), match='123'>

print(ret.group())
#123




ret=re.search('\d+8','12345xxxxx')
找不到就是 None
print(ret)
#None
print(ret.group())
找不到报错


改进:  不让他报错
    

ret=re.search('\d+8','12345xxxxx')
找不到就是 None
print(ret)
#None
if ret:
	print(ret.group())


    

分组

ret=re.search('\d(\d+)(x*)','12345xxxx12125453x')
print(ret)
if ret:
    print(ret.group())
    print(ret.group(1))
    print(ret.group(2))
    
    
 #
<_sre.SRE_Match object; span=(0, 9), match='12345xxxx'>
12345xxxx
2345
xxxx

分组的比较

findall

还是按照完整的正则进行匹配,只是只显示括号里匹配的内容

search还是按照完整的正则进行匹配,

显示也显示匹配到的第一个内容

但是我们可以通过group 方法传参数来获取文组中的内容

.group(0) 和 .group() 一致

.group(n) 来指定获取第n 个分组中 匹配到的内容

为什么 search 中 不需要分组优先 findall需要分组优先

ret = re.findall('<\w+>(<\w+>)</\w+>'),'<h1>jaskdhkasjdh</h1>')
匹配中间的内容   就给需要的内容加上括号   进行提取

search 可以随便匹配

为什么要用分组.以及findall 分组有限的好处到底是什么

exp=1-3*6+6
a+b 或a-b 并计算它的结果

ret= re.search('\d+[+]\d+',exp)
print(ret)
a,b=ret.spilt('+')
print(int(a)+int(b))


简化:
ret= re.search('(\d+)[+](\d+)',exp)
print(ret)
print(ret.group(1))    
print(ret.group(2)) 
print(int(ret.group(1))+int(ret.group(1)))

. 可以匹配任意内容 应该设置 一个 flags=re.S

det=re.findall('class ="title" >(.*?)< / h4 >',ret,flags=re.S)

print(cet)

取消优先显示分组 ?:

re.findall('1(\d)(\d)','123')

[('2','3')]


re.findall('1(\d)(?:\d)','123')

['2']



posted @ 2020-03-07 16:11  小丁变优秀  阅读(182)  评论(0)    收藏  举报