帮助学习的工具 http://tool.chinaz.com/regex/
字符组 []
在一个字符的位置上能出现的内容
[1bc] 是一个范围
[0-9][A-Z][a-z] 匹配三个字符
[abc0-9] 匹配一个字符
[0-9a-zA-Z] 匹配一个字符
[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9X]
\d == [0-9] 也表示匹配一个字符,匹配的是一个数字
\w == [0-9a-zA-Z_] 也表示匹配一个数字字母下划线
\s == [\n \t] 包括回车 空格 和 制表符tab
\n 匹配回车
\t 匹配制表符 (tab)
\D 匹配非数字
\W 匹配非数字字母下滑线
\S 匹配非空白
[\d\D] [\w\W] [\s\S]
正则表达式的语法
作用 : 一种匹配字符串的规则
应用 : 登录注册的表单验证
爬虫 自动化开发 日志分析
1. 元字符
字符组 [] [^] | ()
|的用法 [1-9]\d{16}[0-9X]|[1-9]\d{14} 身份证号
()的用法 [1-9]\d{14}(\d{2}[1-9X])? 身份证号
\d+(\.\d+)? 小数或者整数
\w \d \s(\n,\t, ) \W \D \S
^ $
. 匹配除了换行符之外的所有字符 爬虫容易用,表单不容易用
2. 量词
? 0-1
+ 1-无穷
* 0-无穷
{n},{n,},{n,m}
3.特殊的用法和现象
?的使用
1. 在量词的后面跟了一个 ? 取消贪婪匹配 非贪婪(惰性)模式
?? \ *? \+? \ {n}?
李.{1,3}?和 李莲英和 惰性匹配 回溯算法
最常用 .*?x 匹配任意字符直到找到一个x
总结
元字符
元字符量词 默认贪婪匹配- 回溯算法 (先拿他个最大量,然后往回找匹配的)
元字符量词? 表示惰性匹配 - 惰性匹配 (一个个匹配,有了就停止匹配了)
1、匹配任意长度的正整数 [1-9]\d*
2、匹配小数 -?\d+\.\d+
3、匹配整数或者小数:
-?\d+\.?\d* 有缺陷 1. 2.这样的内容都能被匹配上
-?\d+\.?\d+ 有缺陷 1 2 这样的一位数都匹配不上了
-?\d+(\.\d+)? 准确的
4、匹配负数 -0\.\d+|-[1-9]\d+(\.\d+)?
5、匹配qq号 [1-9]\d{4,11}
6、匹配长度为11位的电话号码 1[3-9]\d{9}
7、长度为8-10位的用户密码 : 包含数字字母下划线和?@
[\w@?]{8,10}
8、匹配验证码:4位数字字母组成的
[\da-zA-Z]{4}
9、从类似
<a>wahaha<\a>
<b>banana<\b>
<h1>qqxing<h1>
<script>salkdjgh<\script>
这样的字符串中,
1)匹配出wahaha,banana,qqxing内容。 >\w+<
2)匹配出a,b,h1这样的内容 <\w+>
10、1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
从上面算式中匹配出最内层的小括号
(-40/5)(9-2*5/3+7/3*99/4*2998+10*568/14)(-4*3)(16-3*2)
\([\d\.+\-*/]+\)
\([^()]+\)
正则表达式中的转义 :
‘\(‘ 表示匹配小括号
[()+*?/$.] 在字符组中一些特殊的字符会现出原形
[-]只有写在字符组的首位的时候表示普通的减号,写在其他位置的时候表示范围[1-9],如果就是想匹配减号 [1\-9]
python中的转义符
‘\n‘ # \转义符 赋予这个n一个特殊的意义 表示一个换行符
print(‘\\n‘) # 取消转义 \n
print(‘C:\\next‘) # 取消转义 C:\next 等同于 print(r‘C:\next‘)
re模块
对字符串 进行匹配
一 、findall (重要)
ret = re.findall(‘\d+‘,‘19874ashfk01248‘) print(ret) # 参数 返回值类型:列表 返回值个数:1 返回值内容:所有匹配上的项 [‘19874‘, ‘01248‘]
二、search (重要)
匹配到
ret2 = re.search(‘\d+‘,‘@$19874ashfk01248‘) print(ret2) # 返回值类型: 正则匹配结果的对象 返回值个数:1 如果匹配上了就返回对象 # <re.Match object; span=(2, 7), match=‘19874‘>
if ret2:print(ret2.group()) # 返回的对象通过group来获取匹配到的第一个结果
# 19874
没匹配到
ret3 = re.search(‘\s+‘,‘19874ashfk01248‘) print(ret3) # 返回值类型: None 如果没有匹配上就是None
三 、match (一般)
ret4 = re.match(‘\d+‘,‘19874ashfk01248‘) print(ret4) # <re.Match object; span=(0, 5), match=‘19874‘> ret5 = re.match(‘\d+‘,‘%^19874ashfk01248‘) print(ret5) # None print(ret4.group()) # 19874
四、替换 python
1、自带替换 replace
print(‘replace789,24utdeedeeeeshf‘.replace(‘e‘,‘H‘,3)) # e替换成H ,替换3个 # rHplacH789,24utdHedeeeeshf
2、re 的sub (一般)
ret = re.sub(‘\d+‘,‘H‘,‘replace789nbc2xcz392zx‘) # 正则,替换内容,字符串 print(ret) # replaceHnbcHxczHzx ret = re.sub(‘\d+‘,‘H‘,‘replace789nbc2xcz392zx,48495‘,1) print(ret) # replaceHnbc2xcz392zx,48495
3、subn(一般)
ret = re.subn(‘\d+‘,‘H‘,‘replace789nbc2xcz392zx‘) #正则,替换值,字符串 print(ret) # 返回一个元组 (替换后的字符串,替换次数) # (‘replaceHnbcHxczHzx‘, 3)
五、切割
split
1、python 内置函数
print(‘alex|83|‘.split(‘|‘)) # [‘alex‘, ‘83‘, ‘‘]
2、re中的split
ret = re.split(‘\d+‘,‘alex83egon20taibai40‘) print(ret) #[‘alex‘, ‘egon‘, ‘taibai‘, ‘‘]
六、进阶方法 - 爬虫\自动化开发
1、compile (重要)-----节省时间
一般都是直接带入正则表达式,直接匹配结果,当要重复使用改正则表达式,程序就要重新编译理解它,继而导致程序效率低
re.findall(‘-0\.\d+|-[1-9]+(\.\d+)?‘,‘alex83egon20taibai40‘) # --> python解释器能理解的代码 --> 执行代码
那,如何让程序更加高效呢? 我们可以使用预编译compile ,程序直接调用编译结果使用即可,不用重复编译了
(节省时间 : 只有在多次使用某一个相同的正则表达式的时候,这个compile才会帮助我们提高程序的效率)
ret = re.compile(‘-0\.\d+|-[1-9]\d+(\.\d+)?‘) res = ret.search(‘alex83egon-20taibai-40‘) res2 = ret.search(‘...‘) res3 = ret.search(‘...‘) ... print(res.group())
2、finditer (重要)--节省空间
print(re.findall(‘\d‘,‘sjkhkdy982ufejwsh02yu93jfpwcmc‘)) ret = re.finditer(‘\d‘,‘sjkhkdy982ufejwsh02yu93jfpwcmc‘) # 得到了一个迭代器(可迭代对象) for r in ret: print(r.group()) -------------------------------- 9 8 2 0 2 9 3
关于分组的坑
findall 关于分组的坑--- 分组的优先显示
优先显示分组内的内容
import re ret = re.findall(‘-0\.\d+|-[1-9]\d*(\.\d+)?‘,‘-1asdada-200‘) print(ret) # [‘‘, ‘‘] ret = re.findall(‘www.baidu.com|www.oldboy.com‘,‘www.oldboy.com‘) print(ret) # [‘www.oldboy.com‘] ret = re.findall(‘www.(baidu|oldboy).com‘,‘www.oldboy.com‘) print(ret) # [‘oldboy‘] ret = re.findall(‘www.(?:baidu|oldboy).com‘,‘www.oldboy.com‘) print(ret) # 取消分组优先(?:) [‘www.oldboy.com‘]
split 遇到分组 会保存被切掉的内容
ret = re.split(‘\d+‘,‘alex83egon20taibai40‘) print(ret)
ret = re.split(‘(\d+)‘,‘alex83egon20taibai40‘) print(ret) # 遇到分组,保存被切掉的内容 ---------------------------------------------------- [‘alex‘, ‘egon‘, ‘taibai‘, ‘‘] [‘alex‘, ‘83‘, ‘egon‘, ‘20‘, ‘taibai‘, ‘40‘, ‘‘]
search遇到分组
通过group(n)就能拿到group中的匹配的内容
ret = re.search(‘\d+(.\d+)(.\d+)(.\d+)?‘,‘1.2.3.4-2*(60+(-40.35/5)-(-4*3))‘) print(ret.group()) print(ret.group(1)) print(ret.group(2)) print(ret.group(3)) --------------------------- 1.2.3.4 .2 .3 .4
小试牛刀
一、要求匹配到表达式"1-2*(60+(-40.35/5)-(-4*3))"中所有整数
1.拿到所有的数,(然后把小数去掉)
import re ret = re.findall(r"\d+(?:\.\d+)?", "1-2*(60+(-40.35/5)-(-4*3))") print(ret)
2.直接匹配所有整数
分组思路,我不想要小数,但是无法避免,我就匹配小数,但是咱不显示你就行了
# 思路是 我们匹配小数|整数,但是小数取消优先显示,优先显示的是后面的整数,即得到结果 ret = re.findall(r"\d+(?:\.\d+)|(\d+)", "1-2*(60+(-40.35/5)-(-4*3))") print(ret) # [‘1‘, ‘2‘, ‘60‘, ‘‘, ‘5‘, ‘4‘, ‘3‘] ret.remove(‘‘) # [‘1‘, ‘2‘, ‘60‘, ‘5‘, ‘4‘, ‘3‘] print(ret)
二、匹配html 标签内容
1、匹配<a>wahaha<\a>
import re ret = re.findall(‘>(\w+)<‘,r‘<a>wahaha<\a>‘) print(ret) # [‘wahaha‘]
2、嘿,那假如想匹配两端标签不同的中间内容呢<a>wahaha</b> (当然这是假设)
# 利用分组! ret = re.search(r‘<(\w+)>(\w+)</(\w+)>‘, r‘<a>wahaha</b>‘) print(ret.group()) print(ret.group(1)) print(ret.group(2)) -------------------------------- <a>wahaha</b> a wahaha
七、分组命名
(?P<name>正则表达式)
1、通过group(分组名),获取值
ret = re.search("<(?P<name>\w+)>\w+</(?P=name)>","<h1>hello</h1>") print(ret.group(‘name‘)) # 结果 :h1 print(ret.group()) # 结果 :<h1>hello</h1>
同样的通过group(n),当然也是可以的呀
ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>") print(ret.group(1)) # print(ret.group()) #结果 :<h1>hello</h1>
同样的 :
ret = re.search(r‘<(?P<tag>\w+)>(?P<c>\w+)</(\w+)>‘, r‘<a>wahaha</b>‘) print(ret.group()) # <a>wahaha</b> print(ret.group(‘tag‘)) # a print(ret.group(‘c‘)) # wahaha
推荐一本正则的书 :《正则指引》 -------- 以python 为基础的书
小拓展 |
1.groups()是什么?
import re ret = re.search(r‘\d+(\.\d)(\d)‘,r‘1.23+2.3+3-4*5‘) print(ret.group()) print(ret.group(1)) print(ret.group(2)) print(ret.groups()) —————————————————————— 1.23 .2 3 (‘.2‘, ‘3‘) # 可知,groups() 获取分组内的内容,以str形式放入元组内
2.split 分组保留
import re ret3 = re.split(‘\d(\w)‘, ‘***1a***2b***3c**‘) print(ret3) # [‘***‘, ‘a‘, ‘***‘, ‘b‘, ‘***‘, ‘c‘, ‘**‘] # 以数字+数字字母下划线 的组合切开,但是保留后面的分组了
25 -1 正则 re模块 (findall、search、match、sub、subn、split、compile、finditer)
原文:https://www.cnblogs.com/zhuangdd/p/12644081.html