正则(python)
\d
匹配数字
*
匹配0个或0个以上
+
匹配1个或1个以上
{n}
匹配n个
字符分类
\d
0到9的数字
\D
除0到9的数字以外的任何字符
\w
字母/数字/下划线字符(可以理解为"单词")
\W
除字母/数字/下划线以外的任何字符
\s
空格/制表符/换行符(可以理解为"空白"字符)
\S
除空格/制表符/换行符以外的任何字符
search
import re
#先将匹配规则编译成Regex对象
pattern = re.complie(r'\d\d\d-\d\d\d-\d\d\d\d')
# 进行匹配, 匹配到则返回一个Match对象, 否则返回None
s = r.search(pattern, 'My number is 123-345-3453')
s.group()
# '123-345-3453'
# 直接使用匹配规则匹配
s = r.search(r'\d\d\d-\d\d\d-\d\d\d\d', 'My number is 123-345-3453')
s.group()
# '123-345-3453'
上面两种方式都可以匹配, 如果规则在多个地方用的话, 编译成Regex文件更加方便, 速度也会比较快
这里的group()
返回被查找字符串中实际匹配的文本
match
match
和search
方法类似, 但有些许区别, 顾明思议
match
是匹配
的意思, 从第一个字符开始匹配, 匹配不到就返回
search
是搜索
的意思, 如果第一个字符匹配不到, 会继续往后匹配, 直到字符结束
m = re.match(r'\d\d\d-\d\d\d-\d\d\d\d', 'My number is 123-345-3453')
print(m)
# None
m = re.match(r'\d\d\d-\d\d\d-\d\d\d\d', '123-345-3453')
m.group()
# 123-345-3453
findall
与search
和match
不同的是, findall()
方法返回的是一个列表(包含匹配到的所有字符), 当有分组时, 返回一个列表(包含多个元组), 代码如下
pattern = re.complie(r'\d\d\d-\d\d\d-\d\d\d\d')
pattern.findall('123-345-3453')
# ['123-345-3453']
pattern = re.complie(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
pattern.findall('123-345-3453aa 345-456-56783')
# [('123', '345', '3453'), ('345', '456', '5678')]
利用括号分组
pattern = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
m = pattern.search('My number is 123-345-3453.')
m.group() # 返回匹配到的文本
# '123-345-3453'
m.group(1) # 返回第1组
# '123'
m.group(1) # 返回第2组
# '345'
m.groups() # 返回一个元组, 包含所有分组
# ('123', '345', '3453')
管道(匹配多个分组)
pattern = re.compile(r'abc|def')
s = pattern.search('abc 234 defdffd')
s.group() # 匹配到的文本
# 'abc'
s = pattern.findall('abc 234 defdffd')
print(s)
# ['abc', 'def']
pattern = re.compile(r'ab(c|d|e|f)') # 匹配abc/abd/abe/abf任意一个
s = pattern.search('abc d abd abefds')
s.group()
# 'abc'
s.group(1) # 返回括号中匹配的文本
#'c'
s.groups() # 返回一个元组, 包含所有分组
# ('c',)
问号实现可选匹配
pattern = re.compile(r'abc(ef)?gh')
s = pattern.search('a string is abcgh')
s.group()
# 'abcgh'
s = pattern.search('a string is abcefgh')
s.group()
# 'abcefgh'
s = pattern.search('a string is abcegh')
s.group()
# None
前两种都可以正常匹配, 但最后一种不能, 看来(ef)?
要么有ef, 要么没有ef, 不能拆分
用星号匹配零次或多次
pattern = re.compile(r'abc(ef)*gh')
s = pattern.search('a string is abcgh')
s.group()
# 'abcgh'
s = pattern.search('a string is abcefefefgh')
s.group()
# 'abcefefefgh'
括号中的字符串出现零次或者多次都可以匹配到
加号匹配一次或多次
+
和*
可以对比一下, 都可以多次匹配, 但是+
至少需要匹配一次
pattern = re.compile(r'abc(ef)+gh')
s = pattern.search('a string is abcgh')
s.group() # 这里由于ef出现零次, 匹配不到
# None
s = pattern.search('a string is abcefefefgh')
s.group()
# 'abcefefefgh'
花括号匹配固定次数
pattern = re.compile(r'abc(ef){3}gh')
s = pattern.search('a string is abcgh')
s.group() # 这里由于ef出现零次, 匹配不到
# None
s = pattern.search('a string is abcefefefgh')
s.group() # 这里ef出现三次, 匹配成功
# 'abcefefefgh'
贪婪匹配和非贪婪匹配(?)
Python正则默认是贪婪匹配
- 贪婪匹配
pattern = re.compile(r'(ab){3,5}') # 匹配3到5次
s = pattern.search('abab')
s.group()
# None
s = pattern.search('abababababab')
s.group()
# 'ababababab'
- 非贪婪匹配
pattern = re.compile(r'(ab){3,5}?')
s = pattern.search('abababababab')
s.group() # 只匹配了3个字符
# 'ababab'
建立自己的字符分类([ ])
\w``\s``\d
范围太大, 很多情况不适用, 这时可以使用[]
自定义字符分类
pattern = re.compile(r'[aio456]')
pattern.findall('adcidfeoa4256')
# ['a', 'i', 'o', 'a', '4', '5', '6']
pattern = re.compile(r'[^aio456]') # 前面加(^)表示除了这些的进行匹配
pattern.findall('adcidfeoa4256')
# ['d', 'c', 'd', 'f', 'e', '2']
pattern = re.compile(r'[0-9a-z]') # 使用短横表示字母或数字的范围
pattern.findall('234dfds')
# ['2', '3', '4', 'd', 'f', 'd', 's']
pattern = re.compile(r'[0-9a-z]+') # 匹配多个字符
pattern.findall('234adf_dffw234')
# ['234adf', 'dffw234']
pattern = re.compile(r'[0-9a-z]*')
p.findall('234adf_dffw234')
# ['234adf', '', 'dffw234', '']
限制开头或结尾(^ $)
pattern = re.compile(r'^Hello') # 以"Hello"开头
pattern.search('Hello ddd')
# <_sre.SRE_Match object; span=(0, 5), match='Hello'>
pattern = re.compile(r'Hello$') # 以"Hello"结尾
pattern.search('aaa Hello')
# <_sre.SRE_Match object; span=(4, 9), match='Hello'>
pattern = re.compile(r'^Hello$') # 开头到结尾为"Hello"
pattern.search('Hello')
# <_sre.SRE_Match object; span=(0, 5), match='Hello'>
通配符( . )
.
匹配除了换行之外的所有字符
pattern = re.compile(r'.a')
pattern.findall('dabaca')
# ['da', 'ba', 'ca']
让.
匹配包括换行之内的所有字符
pattern = re.compile(r'.a', re.DOTALL)
pattern.findall('dabaca')
# ['da', 'ba', 'ca']
( .* )匹配所有字符
.
匹配除了换行所有字符, *
匹配零个或以上文本(任意文本), 因此.*
匹配除了换行的所有字符
-
.*
贪婪匹配, 匹配尽可能多的字符 -
.*?
非贪婪匹配, 匹配尽可能少的字符
p = re.compile('<.*>')
s = p.search('<dfs>df>')
s.group()
# '<dfs>df>'
这里的.*
尽可能多的匹配, 直到找到最后的>
符号
p = re.compile('<.*?>')
s = p.search('<dfs>df>')
s.group()
# '<dfs>'
使用.*?
时, 当匹配到第一个>
符号时结束匹配
不区分大小写(re.I)
使用re.IGNORECASE亦可
pattern = re.compile(r'AcB', re.I)
s = pattern.search('acb')
s.group()
# 'acb'
re.sub替换字符串
sub(pattern, repl, string, count=0, flags=0)
re.sub('abc', 'efg', 'abcdabcd')
# 'efgdefgd'
回顾
-
?
匹配零次或一次前面的分组 -
*
匹配零次或多次前面的分组 -
+
匹配一次或多次前面的分组 -
{n}
匹配n次前面的分组 -
{n,}
匹配n次或更多前面的分组 -
{,m}
匹配零次到m次前面的分组 -
{n,m}
匹配n次到m次前面的分组 -
^aa
必须以aa开头 -
zz$
必须以zz结尾 -
.
匹配所有字符,换行除外(可以参数让其匹配换行) -
\d \w \s
分别匹配数字, 单词和空格(大写则相反) -
[abc]
匹配abc中任意字符 -
[^abc]
匹配除了abc以外的任意字符
网友评论