本文最后更新于:14 天前

正则

在实际的应用中,我们会经常得到用户的输入,在得到用户的输入之后,需要我们对输入进行判断时候合法,比如判断输入的手机号码,从形式上来看是争取的呢?

mu = input('请输入电话号码:')
def phone_number(st):
    st = str(st)
    if len(st) == 11 and st.startswith('1') and st.isdigit() :
        return True
    else:
        print('Phone Number Error')
        return False
print(phone_number(mu))
请输入电话号码:12332112345
True

那有什么简单的方法呢?

正则搜索

match
import re
a = '12345678900'
rm = re.match(r'1\d{10}',a)
print(rm)
<_sre.SRE_Match object; span=(0, 11), match='12345678900'>
import re
a = '12345678900'
rs = re.search(r'1\d{10}',a)
print(rs)
<_sre.SRE_Match object; span=(0, 11), match='12345678900'>

通过对比,可以很明显的发现,下面这种方式能够简单快捷的匹配出电话号码

总结

正则表达式:正则表达式是一种通用的用来简洁表达一组字符串的表达式,因此,正则表达式是和python无关的,在其他的语言或者不同的系统中,是通用的。

匹配:通过正则表达式就可以去匹配现有的字符串。

应用:通过正则匹配,可以迅速的过滤出我们需要的全部或者一部分字符串,查找文本中的特质值(如:病毒)等等。

元字符

正则表达式该如何书写呢?

观察如下两个例子:

In [3]: re.search('a', 'abc')
Out[3]: <_sre.SRE_Match object; span=(0, 1), match='a'>

In [5]: re.search('.', 'ab.cd.de')
Out[5]: <_sre.SRE_Match object; span=(0, 1), match='a'>

在第一个例子中,可以匹配出a

但是下面这个不能匹配,但是下面这个没有匹配出点,而是匹配到 a

这个 . 不是不能匹配到点,而是匹配任意字符,这个点已经被赋予了特殊的含义, .(点)就是一个元字符

元字符

正因为有这些元字符的存在,正则表达式才变得强大.

元字符含义

\b

In [23]: re.search('\bs\b', 'abcdsd s we')

In [24]: re.search(r'\bs\b', 'abcdsd s we')
Out[24]: <_sre.SRE_Match object; span=(7, 8), match='s'>

在正则中,加上r 去掉字符串的转义,以免影响正则的使用

\b匹配一个单词边界,也就是指单词和空格间的位置。

.

In [26]: re.search(r'.', 'abcdsd s we')
Out[26]: <_sre.SRE_Match object; span=(0, 1), match='a'>

In [27]: re.search(r'.', '\nabcdsd s we')
Out[27]: <_sre.SRE_Match object; span=(1, 2), match='a'>

匹配除换行符之外的所有的字符

\d

In [28]: re.search(r'\d',r'abc141342d')
Out[28]: <_sre.SRE_Match object; span=(3, 4), match='1'>

匹配0~9的数字

\s

In [30]: re.search(r'\s',r'abc 141342d')
Out[30]: <_sre.SRE_Match object; span=(3, 4), match=' '>

匹配任意的空白符,包括空格,制表符(Tab),换行符等

\w

In [31]: re.search(r'\w',r'abc 141342d')
Out[31]: <_sre.SRE_Match object; span=(0, 1), match='a'>

匹配字母或数字或下划线或汉字等 \b 表示单词的边界

In [32]: re.search(r'\bc\b',r'abc c 342d')
Out[32]: <_sre.SRE_Match object; span=(4, 5), match='c'>

In [33]: re.search(r'\bbcb\b',r'abc bcb 342d')
Out[33]: <_sre.SRE_Match object; span=(4, 7), match='bcb'>

\.

In [34]: re.search(r'\.',r'ab.c .bcb 342d')
Out[34]: <_sre.SRE_Match object; span=(2, 3), match='.'>

表示匹配点号本身

\D、\S、\W、\B

In [35]: re.search(r'\D','abc.1213')
Out[35]: <_sre.SRE_Match object; span=(0, 1), match='a'>

In [36]: re.search(r'\S','abc.1213')
Out[36]: <_sre.SRE_Match object; span=(0, 1), match='a'>

In [37]: re.search(r'\W','abc.1213')
Out[37]: <_sre.SRE_Match object; span=(3, 4), match='.'>

In [38]: re.search(r'\B','abc.1213')
Out[38]: <_sre.SRE_Match object; span=(1, 1), match=''>

是与小写的相反的作用

\D

In [39]: re.search(r'\D','abc.1213')
Out[39]: <_sre.SRE_Match object; span=(0, 1), match='a'>

除了数字以外的字符

^

In [41]: re.search(r'^ab',r'abc 141342d')
Out[41]: <_sre.SRE_Match object; span=(0, 2), match='ab'>

脱字符,匹配输入字符串的开始的位置

$

In [42]: re.search(r'd$',r'abc 141342d')
Out[42]: <_sre.SRE_Match object; span=(10, 11), match='d'>

匹配输入字符串的结束位置

{}

In [43]: re.search(r'\d{1,3}',r'abc 141 qw 342d')  # 对象,找到一个就不找了
Out[43]: <_sre.SRE_Match object; span=(4, 7), match='141'>

In [44]: re.findall(r'\d{1,3}',r'abc 141 qw 342d')  #列表,全部找出来
Out[44]: ['141', '342']

In [45]: re.findall(r'\d{1,}',r'abc 141 qw 34325252d')
Out[45]: ['141', '34325252']

In [46]: re.findall(r'\d{,5}',r'abc 141 qw 34325252d')
Out[46]: ['', '', '', '', '141', '', '', '', '', '34325', '252', '', '']

In [47]: re.findall(r'\d{0,3}',r'abc 141 qw 34325252d')
Out[47]: ['', '', '', '', '141', '', '', '', '', '343', '252', '52', '', '']

{M,N} M和N 为非负整数,其中M<=N 表示前面的匹配M~N次

{M,} 表示需要匹配M次

{,N} 等价于{0~N}

{N} 表示需要匹配N次

*

In [49]: re.findall(r'\d*',r'abc 141 qw 34325252d')
Out[49]: ['', '', '', '', '141', '', '', '', '', '34325252', '', '']

In [50]: re.findall(r'\d{0,}',r'abc 141 qw 34325252d')
Out[50]: ['', '', '', '', '141', '', '', '', '', '34325252', '', '']

匹配前面的子表达式零次或多次,等价于{0,}

+

In [51]: re.findall(r'\d+',r'abc 141 qw 34325252d')
Out[51]: ['141', '34325252']

In [52]: re.findall(r'\d{1,}',r'abc 141 qw 34325252d')
Out[52]: ['141', '34325252']

匹配前面的子表达式一次或多次,等价于{1,}

?

In [57]: re.findall(r'\d{0,1}',r'ab5252d')
Out[57]: ['', '', '5', '2', '5', '2', '', '']

In [58]: re.findall(r'\d?',r'ab5252d')
Out[58]: ['', '', '5', '2', '5', '2', '', '']

匹配前面的子表达式零次或一次,等价于{0,1}

贪婪与非贪婪

*?、+?
In [61]: re.findall(r'\d*?',r'ab5252d')
Out[61]: ['', '', '', '', '', '', '', '']

In [62]: re.findall(r'\d+?',r'ab5252d')
Out[62]: ['5', '2', '5', '2']
In [65]: st ="<html>aaaa</html><td>bbbb</td>"

In [66]: re.findall(r'<.*>',st)
Out[66]: ['<html>aaaa</html><td>bbbb</td>']

In [67]: re.findall(r'<.*?>',st)
Out[67]: ['<html>', '</html>', '<td>', '</td>']

在非贪婪模式下,始终找最短匹配

[]字符集合

[] 字符类,将要匹配的一类字符集放在[]里面

In [68]: re.findall(r'[\d]',r'abc 141 qw 34325252d')
Out[68]: ['1', '4', '1', '3', '4', '3', '2', '5', '2', '5', '2']

In [69]: re.findall(r'[0-9]',r'abc 141 qw 34325252d')
Out[69]: ['1', '4', '1', '3', '4', '3', '2', '5', '2', '5', '2']

In [70]: re.findall(r'[a-z]',r'abc 141 qw 34325252d')
Out[70]: ['a', 'b', 'c', 'q', 'w', 'd']

[ . ? * ( ) {} ] 匹配里面的这些符号

[0-9] 匹配0到9的数字相当于\d

[^\d] 匹配除数字以外的字符,相当于\D取反的意思

[a-z] 匹配所有的小写字母

[^a-z] 匹配非小写字母

| 相当于或(or)分支条件

()分组匹配

() 分组,将要匹配的一类字符集放在()组成一个小组

In [75]: re.findall(r'(32)',r'abc 141 qw 34325252d')
Out[75]: ['32']

In [76]: re.findall(r'a(3|2)',r'a3 a2 a23 ')
Out[76]: ['3', '2', '2']

In [77]: re.findall(r'a([32])',r'a3 a2 a23 ')
Out[77]: ['3', '2', '2']

分组匹配匹配() 内的字符串组合

re模块

compile

编译正则表达式为模式对象

当正则表达式多次使用,可以采用这种方式

In [78]: r = re.compile(r'\das')

In [79]: r.findall('1as234')
Out[79]: ['1as']

sub

字符串替换

In [80]: re.sub('i','o','pythin***pythin',1)
Out[80]: 'python***pythin'

In [81]: re.sub('i','o','pythin***pythin',2)
Out[81]: 'python***python'

In [82]: re.sub('i','o','pythin***pythin')
Out[82]: 'python***python'

match

从字符串开始位置匹配

In [83]: re.match(r'\d','123ad')
Out[83]: <_sre.SRE_Match object; span=(0, 1), match='1'>

In [84]: re.match(r'\d','a123ad')

group

得到匹配到的元素

In [94]: re.search(r'\d{1,3}',r'abc 141 qw 342d')
Out[94]: <_sre.SRE_Match object; span=(4, 7), match='141'>

In [95]: li = re.search(r'\d{1,3}',r'abc 141 qw 342d')

In [96]: li.group()
Out[96]: '141'

start

得到开始位置

In [97]: li.start()
Out[97]: 4

end

得到结束位置

In [98]: li.end()
Out[98]: 7

span

得到位置范围

In [99]: li.span()
Out[99]: (4, 7)

注意:

这几个方法在search中也存在

扩展

在re中也有和字符串一样的split方法

In [85]: re.split(r'\s',' cee')
Out[85]: ['', 'cee']

In [86]: re.split(r'\s','aa bb cc dd')
Out[86]: ['aa', 'bb', 'cc', 'dd']

In [87]: re.split(r'[\s|c]','aa bb c dd ee')
Out[87]: ['aa', 'bb', '', '', 'dd', 'ee']