什么是正则表达式?
正则表达式并不仅仅是python的专利,几乎其他的语言都有正则表达式。就比如bash就有正则表达式命令--grep,个人感觉python中的正则表达式类似于
grep -o
正则表达式是用于处理字符串的强大工具,虽然效率上可能不高,但是功能强大!
正则表达式设定了一系列语法,比如说“ . ”表示任意单个字符,\d表示单个数字…… 通过组合这些规则我们可以形成一个pattern(模式)!凡是符合这个pattern的字符串,我们就认为它被匹配了,否则,则代表这个字符串是不合法的!
正则表达式的语法:
单个字符 | 具体说明 |
. | 匹配任意字符(除了换行符\n) |
[] | 匹配字符集,[0-1]表示数字,[a-z]表示小写字母 |
\ | 转义字符,改变其后字符的原意 |
[^] | 非 |
\d | 与[0-9]功能相同,表示数字 |
\D | 非数字,即[^\d] |
\s | 空白字符即:[<空格>\t\r\f\n\v] |
\S | 非空白字符 |
\w | 单词字符[a-zA-Z0-9] |
\W | 非单词字符[^\w] |
上面表格中就是单个字符。当我们要匹配一个字母时,我们可以这样写:[a-z] .但是如果我们要匹配两个字符的时候该怎么办?
大家可能会想到这样:[a-z][a-z] 好,用这样的方法也可以。但是如果我们要匹配10个甚至数百个或者不限定字符的长度该怎么办?那我们就要用到数量词了。
数量词 | 说明 |
* | 匹配前面的字符任意次(0次或者无限次) |
+ | 匹配前面的字符一次或者无限次 |
? | 匹配前面的字符0次或者1次 |
{m,n} | 匹配前面的字符最小m次,最多n次 |
当我们想要匹配以a开头的字符串时,就需要用到边界匹配:
^ | 匹配字符串开头,在多行模式中匹配每一行的开头 |
$ | 匹配字符串结尾,在多行模式中匹配每一行的结尾 |
\A | 仅匹配字符串开头 |
\Z | 仅匹配字符串结尾 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er' |
逻辑字符与分组:
| | 类似于或 |
() | 匹配括号内的表达式,也表示一个组 |
(?Pname..) | 分组,除了原有的编号外再指定一个额外的别名 |
\n | 引用第n个分组的表达式匹配到的字符 |
(?P=name) | 引用别名为name的分组表达式匹配到的字符 |
另外因为python中也使用\作为转义字符,而正则表达式也需要\作为转义字符,假如你需要匹配文本中的字符"\",则需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠。为了避免这种复杂的情况,python为我们提供了r前缀(原生字符串)!r'pattern'pattern中的所有字符串表示本意,也就是\就是\,不代表转义字符了!
Python提供re
模块,包含所有正则表达式的功能,所以如果我们要使用正则表达式的话,需要:
import re
python正则表达式常用的5种操作:
1 re.match("pattern","string") :该方法从头部开始匹配,若头部符合pattern则返回一个Match对象否则,则返回None)
import re ret=re.match('[a-z]','1shdkfasdf') print(ret) 结果:None import re ret=re.match('[a-z]','shdkfasdf') print(ret) 结果:<_sre.SRE_Match object; span=(0, 1), match='s'>
常用该方法判断是否匹配:
import re
input_str='ashdfjhakdsf'
if re.match('[a-z]',input_str):
print('ok!!')
else:
print('not found!!')
2 re.search('pattern',' string'):匹配整个字符串,直到找到一个匹配,若找到一个匹配,则返回一个Match对象,没有则返回None。
print(re.search('[0-9]{3}','sdfkj123')) 结果:<_sre.SRE_Match object; span=(5, 8), match='123'> #一般这样用 if re.search('[0-9]{3}','sdfkj123'): print('ok!!') else: print('not found!!')
3 re.split():切分字符串
有的同学就要问了,我们不是有str.split()或者list.split……方法来切分么,为啥还要用这个呢?
请看实例:
a='a s d g' print(a.split(' ')) 结果:['a', 's', 'd', '', '', '', 'g'] #当字符串中有多个连续的空格时,切分的结果就是这么的不尽如人意! a='a s d g' print(re.split('\s+',a)) 结果:['a', 's', 'd', 'g']
4 re.findall():找到所有的匹配到的字符并以list的方式返回。
ret=re.findall('a','askdjflas') print(ret)
结果:['a', 'a']
5 re.sub('pattern','替换为','string',count=):将匹配到的字符替换,可以指定次数。
ret=re.findall('a','askdjflas') print(ret) 结果:1skdjfl1s
正则表达式应用实例:
匹配手机号:
info='my phone is 18766666666' ret=re.search('1[358]\d{9}',info) print(ret.group()) 结果:18766666666
匹配ip v4地址:
info='my phone is 18766666666,my ip is 2.187.5.6' ret=re.search('(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}',info) print(ret.group()) 结果:2.187.5.6