第十九天
re模块-正则表达式
什么是正则表达式
一套规则,匹配字符串的规则
可以做什么
- 检测字符串是否合法--表单验证
- 用户输入,提前检测
- 提高效率,减轻服务器压力
- 从一个大文件中找到符合规则的内容--日志分析/爬虫
- 高效从一大段文字中找到符合规则的内容
正则规则
所有的规则中的字符就可以刚好匹配到字符串中的内容
元字符
字符组[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 停止
原理:
- \d{3,} 先把所有的匹配完 贪婪算法
- 再从最后一个往回找 回溯算法
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
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']

浙公网安备 33010602011771号