[Python] Python正则表达式

正则表达式

字符匹配

1 - 普通字符

大多数字母和字符一般都会和自身匹配,如正则表达式test会和字符串‘test’完全匹配


2 - 元字符  ^  $  *  +  ?  {}  []  \  |  ()

1) [ ]

常用来匹配一个字符集:[abc]; [a-z

元字符在 [] 中不起作用:[akm$]

补集匹配不在区间范围内的字符: [^5]


从给定的字符串中查找符合规则的数据

>>> import re

>>> s = r'abc'

>>> re.findall(s,'aaaaaaaaaaaaaa')
[]
>>> re.findall(s,'abcaaaaaaaaaaaaabcaaaaaaaabc')
['abc', 'abc', 'abc']
>>>

>>> st = 'top tip tqp twp tep'
>>> res = r'top'
>>> re.findall(res,st)
['top']
>>> res = r'tip'
>>> re.findall(res,st)
['tip']


查找给定字符串中是否包含tip或者top(t开头p结尾,中间是i或者o)

>>> res = r't[io]p'
>>> re.findall(res,st)
['top', 'tip']

查找除了tip和top之外的字符串 - 取反

>>> res = r't[^io]p'
>>> re.findall(res,st)
['tqp', 'twp', 'tep']
>>> 


2) ^匹配行首

>>> s = 'hello world,hello boy'
>>> r = r'hello'
>>> re.findall(r,s)
['hello', 'hello']
>>> r = r'^hello' 
>>> re.findall(r,s)
['hello']
>>> 


3) $匹配行尾

>>> r = r'boy$'
>>> re.findall(r,s)
['boy']
>>> 


3) \ 反斜线后面可以加不同的字符以表示不同特殊意义,也可以用于取消所有的元字符: \[ 或 \\

\d 匹配任何十进制数;它相当于类[0-9]

>>> r = r'[0-9]'
>>> re.findall(r,'012325436548768568')
['0', '1', '2', '3', '2', '5', '4', '3', '6', '5', '4', '8', '7', '6', '8', '5', '6', '8']
>>> r=r'\d'
>>> re.findall(r,'012325436548768568')
['0', '1', '2', '3', '2', '5', '4', '3', '6', '5', '4', '8', '7', '6', '8', '5', '6', '8']
>>> 

\D 匹配任何非数字字符;它相当于类[^0-9]

\s 匹配任何空白字符;它相当于类 [\t\n\r\f\v]

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

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

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


\转义^

>>> r = r'\^abc'
>>> re.findall(r,'^abc ^abc ^abc')
['^abc', '^abc', '^abc']
>>> 


4) 重复:正则表达式第一宫内就是能够匹配不定长的字符集,另一个功能就是你可以指定正则表达式的一部分的重复次数

>>> r = r'^010-\d\d\d\d\d\d\d\d'
>>> re.findall(r,'010-87654321')
['010-87654321']
>>> r = r'^010-\d{8}'
>>> re.findall(r,'010-87654321')
['010-87654321']
>>> 

5) * :指定前一个字符可以被匹配零次或更多次,而不是只有一次。匹配引擎会试着重复尽可能多的次数(不超过整数界定范围,20亿)

a[bcd]*b-- 'abcdb'
>>> re.findall(r,'a')
['a']
>>> re.findall(r,'ab')
['ab']
>>> re.findall(r,'abbbbbbbbbbbbbbb')
['abbbbbbbbbbbbbbb']
>>> 


6) +:表示匹配一次或多次

>>> r = r'ab+'
>>> re.findall(r,'a')
[]
>>> re.findall(r,'abbbb')
['abbbb']
>>> 


7) ?:匹配一次或零次,可以用来标识某事物是可选的,可有可无的。或者最小匹配(贪婪模式,非贪婪模式)

允许 - 可以出现或者不出现,不能出现多次

>>> r = r'^010-?\d{8}$' 
>>> re.findall(r,'010--87654321')
[]
>>> re.findall(r,'010--87654321')
[]
>>> re.findall(r,'010876543219')
[]
>>> re.findall(r,'01087654321')
['01087654321']
>>> re.findall(r,'010-87654321')
['010-87654321']
>>> 

贪婪匹配,最大的匹配

>>> r = r'ab+'
>>> re.findall(r,'abbbbbbbbbbb')
['abbbbbbbbbbb']
>>> 

非贪婪匹配,最小的匹配

>>> r = r'ab+?'
>>> re.findall(r,'abbbbbbbbbbb')
['ab']
>>> 


8) {m,n} :至少重复m次,至多重复n次。m和n是十进制数。该限定符的意思是至少有m个重复,至多到n个重复。 a/{1,3}b

忽略m会认为下边界是0,而忽略n的结果将是上边界无穷大(实际上是20亿)

{0,}等同于*, {1,} 等同于+,而{0,1}则与?相同。如果可以的话,最好用*,+ 或?

>>> r = r'a{1,3}'
>>> re.findall(r,'a')
['a']
>>> re.findall(r,'aa')
['aa']
>>> re.findall(r,'b')
[]
>>> re.findall(r,'aaab')
['aaa']
>>> re.findall(r,'ababa')
['a', 'a', 'a']
>>> 

使用正则表达式
re模块提供了一个正则表达式引擎的接口,可以让你将REstring编译成对象并用它们来进行匹配。
编译正则表达式
>>> r1 = r'\d{3,4}-?\d{8}'
>>> re.findall(r1,'010-874654321')
['010-87465432']
>>> p_tel = re.compile(r1)

>>> print(p_tel)
re.compile('\\d{3,4}-?\\d{8}')
>>>

编译之后的正则比编译之前的正则匹配更快
>>> p_tel.findall('010-87654321')
['010-87654321']


re.compile()也可接受可选的标志参数,常用来实现不同的特殊功能和语法变更
re.I是编译正则方法的一个属性,大小写都匹配
>>> a_re = re.compile(r'abcd',re.I)
>>> a_re.findall('ABCDabcd')
['ABCD', 'abcd']


反斜杠的麻烦:字符串前加r 反斜杠就不会被任何特殊方式处理


执行匹配
RegexObject 实例有一些方法和属性,完整的列表可以查阅PythonLibrary Reference
方法/属性           作用
match()    决定RE是否在字符串刚开始的位置匹配,通常用来判断匹配是否成功
有相应的数据会返回一个对象,没有的话会返回一个空值
>>> a_re.match('abcd hello')
<_sre.SRE_Match object; span=(0, 4), match='abcd'>
>>> a_re.match('hello')
>>> 

>>> x = a_re.match('hello')
>>> if x:
...     pass
... 
>>> 

search()   扫描字符串,找到这个RE匹配的位置,没有的话返回空
>>> a_re.search('abcd')
<_sre.SRE_Match object; span=(0, 4), match='abcd'>
>>> a_re.search('abcdeabcd')
<_sre.SRE_Match object; span=(0, 4), match='abcd'>
>>> a_re.search('deaabcdeabcd')
<_sre.SRE_Match object; span=(3, 7), match='abcd'>
>>>

findall()   找到RE匹配的所有子串,并把它们作为一个列表返回

finditer()   找到RE匹配的所有子串,并把它们作为一个迭代器返回
迭代器有可以使用迭代器的方法, __next__等
>>> a_re = re.compile(r'abcd',re.I)
>>> a_re
re.compile('abcd', re.IGNORECASE)
>> x = a_re.finditer('abcsafaabcdefwefBCDEEF')
>>> x.__next__()
<_sre.SRE_Match object; span=(7, 11), match='abcd'>
>>> 

如果没有匹配到的话,match()和search() 会返回None。如果成功的话,返回MatchObject实例。


MatchOject实例方法
group: 返回被RE匹配的字符串
>>> y = a_re.match('abcd hello')
>>> y.group()
'abcd'
>>> y.group(1)
Traceback (most recent call last):
  File "", line 1, in 
IndexError: no such group
>>> y.group(0)
'abcd'
>>> 


start(): 返回匹配开始的位置
end(): 返回匹配结束的位置
span(): 返回一个元组包含匹配(开始,结束)的位置

实际程序中,最常见的做法是将MatchObject 保存在一个变量里,然后检查它是否为None
p = re.compile(... )

m = p.match('string goes here')

if m:

    print('match found:', m.group())

else:

    print('not match')



模块级函数
re模块也提供了顶级函数调用如match(), search(). sub(), subn(), split(), findall()等。用help(re.sub())看用法
sub(),sub()用于替换字符串
>>> rs = r'h...o'
>>> re.sub(rs,'python','hello hallo hawwl')
'python python hawwl'
>>> re.subn(rs,'python','hello hallo hawwl')
('python python hawwl', 2)


split()分割
>>> ip = '192.168.1.1'
>>> ip.split('.')
['192', '168', '1', '1']
>>> s = '123+456-789*125'


因为+-*符号在元字符串中,要转义

>>> re.split(r'[\+\-\*]',s)
['123', '456', '789', '125']
>>> 



编译标志-flags
MULTILINE,M,多行匹配,影响^和$
当我们用正则匹配的字符串占多行时,re.M属性
>>> s = '''
... hello world
... world hello
... hello world hello
... world here
... '''
>>> s
'\nhello world\nworld hello\nhello world hello\nworld here\n'
>>> r = r'^world'
>>> re.findall(r,s)
[]
>>> re.findall(r,s,re.M)
['world', 'world']

VERBOSE,X  能够使用REs的verbose状态,使之被组织得更清晰易懂
当我们定义的正则是多行的时候,用re.X属性
>>> tel = r'''
... \d{3,4}
... -?
... \d{8}
... '''
>>> re.findall(tel,'010-12345678')
[]
>>> re.findall(tel,'010-12345678',re.X)
['010-12345678']
>>> 
>>> 

分组
匹配一个邮箱地址:
\w{3}前三位可以是任意数字字母
@
\w+  一位或多位数字字母
(.com|.cn)  .com 或 .cn结尾,() 分组
>>> email = r'\w{3}@\w+(\.com|\.cn)'
>>> re.match(email,'[email protected]')
<_sre.SRE_Match object; span=(0, 11), match='[email protected]'>
>>> re.match(email,'[email protected]')
<_sre.SRE_Match object; span=(0, 11), match='[email protected]'>
>>> re.match(email,'[email protected]')
<_sre.SRE_Match object; span=(0, 10), match='[email protected]'>
>>> re.match(email,'[email protected]')
>>> 

当有分组时,findall()优先返回分组当中的数据
>>> re.findall(email,'[email protected]')
['.com']
>>> 


当有分组时,findall()优先返回分组当中的数据。下面的例子用分组优先返回src后面的字符串,爬虫用法
>>> s = '''
... hhsdj fsdg hello src=python yes fsdgfsdg
... sfgsg src=123 yes dfsfg
... src=2423 yes fs
... hello src=yyyyy1 yes fdsgs
... '''
>>> r1 = r'src=(.+) yes'
>>> re.findall(r1,s)
['python', '123', '2423', 'yyyyy1']
>>> r1 = r'hello src=.+ yes'

>>> re.findall(r1,s)
['hello src=python yes', 'hello src=yyyyy1 yes']
>>> r1 = r'hello src=(.+) yes'
>>> re.findall(r1,s)
['python', 'yyyyy1']
>>> 

你可能感兴趣的:(Python)