第二十四篇 python正则表达式(全面解析,让匹配无懈可击)

心得:又是充实的一天,望自己每天都过的充实起来~~~

为什么需要用到正则表达式,那我告诉你,不学正则表达式,你就体验不到那种快乐~它可以匹配任何你需要的字符。

1.函数方法:

match()
如果 string 的 开始位置 能够找到这个正则样式的任意个匹配,就返回一个相应的 匹配对象。如果没有返回None,只匹配开头。

>>> s="absdfab"
>>> m=re.match(r'sd',s)
>>> print(m)
None

search()
扫描整个 string 寻找第一个匹配的位置, 并返回一个相应的 匹配对象。如果没有匹配,就返回 None;可作为判断。

>>> s="absdfab"
>>> c=re.search(r'ab',s)
>>> c
<re.Match object; span=(0, 2), match='ab'>
>>> bool(c)
True

findall()
找到正则匹配的所有子字符串,并将它们作为列表返回。

>>> s="absdfab"
>>> f=re.findall(r'a',s)
>>> f
['a', 'a']

sub()
找到正则匹配的所有子字符串,并将它们替换成一个新的字符串再返回

>>> s="absdfab"
>>> u=re.sub('a','A',s)
>>> u
'AbsdfAb'

2.匹配

2.1普通字符匹配

绝大部分普通字符,比如 ‘A’, ‘a’, 或者 ‘0’,都是最简单的正则表达式。它们就匹配自身。你可以拼接普通字符,所以 last 匹配字符串 ‘last’

>>> s="sabcunlmrf;"
>>> a=re.findall(r'abc',s) #全部匹配
>>> b=re.findall(r'[abc]',s) #逐个匹配
>>> a
['abc']
>>> b
['a', 'b', 'c']

2.2特殊字符匹配

\d
匹配任何十进制数字;这等价于类 [0-9]。

>>> s='asd345kl2'
>>> b=re.findall(r'\d',s)
>>> b
['3', '4', '5', '2']

\D
匹配任何非数字字符;这等价于类 [^0-9]。

>>> s='asd345kl2'
>>> c=re.findall(r'\D',s)
>>> c
['a', 's', 'd', 'k', 'l']

\s
匹配任何空白字符;这等价于类 [ \t\n\r\f\v]。

>>> s='asd345 kl2'
>>> b=re.findall(r'\s',s)
>>> b
[' ']

\S
匹配任何非空白字符;这相当于类 [^ \t\n\r\f\v]。

>>> s='asd345 kl2'
>>> b=re.findall(r'\S',s)
>>> b
['a', 's', 'd', '3', '4', '5', 'k', 'l', '2']

\w
匹配任何字母与数字字符;这相当于类 [a-zA-Z0-9_]。

>>> s='asd345 kl2'
>>> b=re.findall(r'\w',s)
>>> b
['a', 's', 'd', '3', '4', '5', 'k', 'l', '2']

\W
匹配任何非字母与数字字符;这相当于类 [^a-zA-Z0-9_]。

>>> s='asd345 kl2'
>>> b=re.findall(r'\W',s)
>>> b
[' ']

.
(点) 在默认模式,匹配除了换行的任意字符。

>>> s='asd345 kl2'
>>> b=re.findall(r'.',s)
>>> b
['a', 's', 'd', '3', '4', '5', ' ', 'k', 'l', '2']

|
或者“or”运算符。 如果 A 和 B 是正则表达式,A|B 将匹配任何与 A 或 B 匹配的字符串。

>>> s='asd345 kl2'
>>> b=re.findall(r'a|k',s)
>>> b
['a', 'k']

^
在行的开头匹配。

>>> s='asd345 kl2'
>>> b=re.findall(r'^as',s)
>>> b
['as']
>>> b=re.findall(r'^s',s)
>>> b
[]

$
匹配行的末尾,定义为字符串的结尾,或者后跟换行符的任何位置。

>>> s='asd345 kl2'
>>> b=re.findall(r'l2$',s)
>>> b
['l2']

2.3 格式数量限定
*
对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 匹配次数大于等于零。

>>> s="helloooabc"
>>> b=re.findall(r'o*',s)
>>> b
['', '', '', '', 'ooo', '', '', '', '']

+
对它前面的正则式匹配1到任意次重复。 匹配次数大于一。

>>> s="helloooabc"
>>> b=re.findall(r'o+',s)
>>> b
['ooo']

?
对它前面的正则式匹配0到1次重复。 ab? 会匹配 ‘a’ 或者 ‘ab’。匹配次数一或零。

>>> s="helloooabc"
>>> b=re.findall(r'lo?',s)
>>> b
['l', 'lo']

“{m}”
对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败。比如, a{6} 将匹配6个 ‘a’ , 但是不能是5个。

>>> s="helloooabc"
>>> b=re.findall(r'o{2}',s)
>>> b
['oo']

“{m, n}”
对正则式进行 m 到 n 次匹配,在 m 和 n 之间取尽量多。优先匹配多次

>>> s="helloooabc"
>>> b=re.findall(r'o{2,3}',s)
>>> b
['ooo']

{m,n}?
前一个修饰符的非贪婪模式,只匹配尽量少的字符次数。优先匹配少次

>>> s="helloooabc"
>>> b=re.findall(r'o{2,3}?',s)
>>> b
['oo']

3 贪婪模式和懒惰模式
重复修饰符 (*, +, ?, {m,n}, 等) 不能直接嵌套。正常使用过程中,我们的匹配模式属于贪婪模式,优先尽可能匹配多的,当我们在限定词之后加?之后,会变为懒惰模式,优先匹配少的。看例子:

>>> s="helloooabc"
>>> b=re.findall(r'o+',s) #一次匹配3个
>>> b
['ooo']
>>> b=re.findall(r'o+?',s) #一次匹配一个,匹配三次
>>> b
['o', 'o', 'o']

4.分组
(…)
(组合),匹配括号内的任意正则表达式,分几组,就会组成几个元素的元组。

>>> s='helloooabc'
>>> b=re.findall(r'(ab)(c)',s)
>>> b
[('ab', 'c')]

优先匹配括号内表达式,括号外匹配不捕获。

>>> s='asd345 kl2'
>>> b=re.findall(r'(d3)45',s)
>>> b
['d3']

(?:…)
正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。

>>> s="asfgphone:95271314abcde"
>>> b=re.findall(r'phone:\d+',s)
>>> b
['phone:95271314']   #直接匹配会存在phone
>>> b=re.findall(r'(?:phone:)(\d+)',s)  #使用分组?:会隐藏phone
>>> b
['95271314']

位置界定:
解释一下:你想匹配一段pass code,但这段code的格式和fail的格式一致,你只需要code,所以外加一个描述pass的形式,它会去匹配,但不返回。

(?=pattern) 后界定:

>>> s="1234567:pass 7654321:fail"
>>> b=re.findall('\d{7}:pass',s)   #正常匹配pass code
>>> b
['1234567:pass']
>>> b=re.findall('\d{7}(?=:pass)',s)  #位置界定pass code
>>> b
['1234567']

(?!pattern) 后不界定

去匹配不是pass 的code

>>> s="1234567:pass 7654321:fail"
>>> b=re.findall('\d{7}(?!:pass)',s)
>>> b
['7654321']

(?<=pattern) 前界定

匹配tian的电话号码

>>> s="tian:95271314 jian:12345678"
>>> b=re.findall('(?<=tian:)\d{8}',s)
>>> b
['95271314']

(?<!pattern) 前不界定

>>> s="tian:95271314 jian:12345678"
>>> b=re.findall('(?<!tian:)\d{8}',s)
>>> b
['12345678']

小练习:

1、长度为8-10的用户密码(以字母开头、数字、下划线)

^[a-zA-Z]\w{7,10}$

3、电子邮箱验证:

>>> s="www.309111985@qq.com www.123456789@163.com www.ashkjdbj@asdh"
>>> b=re.findall(r'w{3}\.\w+@\w+\.\w+',s)
>>> b
['www.309111985@qq.com', 'www.123456789@163.com']

4、URL地址验证:

#1种:
>>> s="https://www.baidu.com as"
>>> b=re.findall(r'https://w{3}\.\w+\.\w+',s)
>>> b
['https://www.baidu.com']
#第2种:
有些网站比较长~
>>> s="https://www.baidu.com as https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=python%E6%AD%A3%E5%88%99%E5%8C%B9%E9%85%8D%E7%BD%91%E7%AB%99&oq=%25E6%25AD%25A3%25E5%2588%2599%25E4%25B9%25A0%25E9%25A2%2598&rsv_pq=b217d62600343d21&rsv_t=e416DGFgpSiQ8nJHMn5vMSxeAkacXdM56vEB6s7qObv1C%2B%2FIIBvP4PyEDx4&rqlang=cn&rsv_enter=1&rsv_dl=tb&inputT=7127&rsv_sug3=54&rsv_sug1=8&rsv_sug7=101&rsv_sug2=0&rsv_sug4=8071&rsv_sug=9"
>>> b=re.findall(r'https://[^\s]*',s)
>>> b
['https://www.baidu.com', 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=python%E6%AD%A3%E5%88%99%E5%8C%B9%E9%85%8D%E7%BD%91%E7%AB%99&oq=%25E6%25AD%25A3%25E5%2588%2599%25E4%25B9%25A0%25E9%25A2%2598&rsv_pq=b217d62600343d21&rsv_t=e416DGFgpSiQ8nJHMn5vMSxeAkacXdM56vEB6s7qObv1C%2B%2FIIBvP4PyEDx4&rqlang=cn&rsv_enter=1&rsv_dl=tb&inputT=7127&rsv_sug3=54&rsv_sug1=8&rsv_sug7=101&rsv_sug2=0&rsv_sug4=8071&rsv_sug=9']
>>>

5、电话号码的验证:我们知道在现实生活中,电话号码的区号可以是三位的也可以是4位的:

>>> s="012-12345678 0123-1234567 +8617521050772"
>>> b=re.findall(r'0\d{2}-\d{8}|0\d{3}-\d{7}|\+\d{13,15}',s)
>>> b
['012-12345678', '0123-1234567', '+8617521050772']

6、简单的身份证号验证:\d{15}|\d{18}$

>>> s='123456789123456 123456789123456789 12345678912345678X'
>>> b=re.findall(r'\d{14}\w{1}(?:\s)|\d{17}\w{1}',s)
>>> b
['123456789123456 ', '123456789123456789', '12345678912345678X']

附加:
当存在多个条件需要匹配时,如文本出现error或fail字符时,我们可以使用|来隔离匹配:

import re
r=re.search(r'error|fail',line)

search 用于判断
findall用于取值为到列表

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值