标签:gic 多次 数值 搜索 忽略 加强 purge imp name
? 我们在学习python
的路途上,有许多需要操作文本数据的场景。无论是前后端/数据库都需要处理文本数据。处理文本时候,正则表达式给我们提供了强大的搜索,匹配,抽取,替换等功能。
regex
)? 正则表达式由一些字符和特殊符号组成的字符串,用来描述模式的重复或者表述多个字符。按照某种特定的模式匹配一系列有相似特征的字符串。python
为我们提供了内置库re
来支持正则表达式。
pattern-matching
)
searching
)
re
中的search()
方法实现matching
)
re
中的match()
方法实现import re
my_str = ‘abcaabccc‘
# 返回的嗾使re模块中的Match的实例对象
res_search = re.search(r‘abc‘, my_str) # <re.Match object; span=(0, 3), match=‘abc‘>
res_match = re.match(r‘abc‘, my_str) # <re.Match object; span=(0, 3), match=‘abc‘>
re
模块中的Match
类实例对象,如果失败则返回None。? 上面我们只是使用固定的字符在匹配,这种功能查查某些字符是否在字符串中还可以,但是这并不是我们需要的功能。元字符可以帮助我们给模式加更多的花样。
. ^ * $
等\d \w \s \b
等(?<name>...)
等|
正则表达式1|正则表达式2
union
,logicla or
(逻辑或)regex_1 = r‘abc‘
regex_2 = r‘aa‘
regex_1 | regex_2 # 匹配的字符串 ‘abc‘或者‘aa‘
.
\n
不包含在内S
或者DOTALL
],该标记能够推翻这个限制。regex = ‘.‘ # 匹配任意字符
regex_1 = ‘..‘ # 匹配任意两个字符
regex_2 = ‘r.l‘ # 匹配rxl x可以是任意字符
^
regex = ‘^a‘ # 以a开头的字符
$
regex = ‘a$‘ # 以a结尾的字符
regex = "^baidu$" # 限制字符为baidu
\b
^
,$
regex = ‘the‘ # 匹配任何含有the的字符串
regex_1 = ‘\bthe‘ # 匹配以the开头的字符串
regex_2 = ‘the\b‘ # 匹配以the结尾的字符串
regex_2 = ‘\bthe\b‘ # 匹配字符串the
\B
regex = ‘\Bthe‘ # 包含the但是不是起始字符串
[]
my_str = ‘abc‘
regex = r‘a[bd]c‘ # 匹配包含abc 或者 adc 的字符串
? 匹配指定的字符范围:使用方括加上连字符-
:例如[A-Z]
表示所有大写字符或者[0-9]
所有单个数值数字。如果在方括里加上一个脱字符^
,表示不匹配给定字符集中的任何一个字符。
regex = r‘[a-z][R-T][0-9]‘ # 三个字符,第一个为任意一个小写字母,第二个为大写的R|S|T,第三个为任意数字
regex_1 = r‘[^0-9]‘ # 除数字以外的任意字符
? 前面我们都是在单个字符的进行匹配,我们可以通过闭包操作来控制它的频数。
*
regex = r‘la*‘ # ex: l la la la...a
+
regex = r‘la+‘‘ # ex: la laa la...a
?
regex = r‘la?‘ # ex: l la
{}
{N}
匹配左侧表达式N
次{M,N}
匹配左侧表达式M
次~N
次regex = r‘a{3}‘ # aaa
regex_1 = r‘a{1,3}‘ # 匹配字符a 至少1次 最多3次
?
紧跟着任何使用闭合操作符的后面,他将要求正则表达式尽可能少的次数匹配。这里涉及的知识点是贪婪匹配和非贪婪匹配\d
[0-9]
\w
[a-zA-Z0-9]
\D
[^0-9]
\W
[^a-zA-Z0-9]
? 用圆括号包裹任何正则表达式,可以保存匹配成功的字符串内容。使用圆括号可以实现以下两个功能中任意一个或者两个。
()
my_str = ‘1993-08-22‘ # 字符串出生的年月日
regex = r‘(\d{4})-([0|1]\d)-([0-3]\d)‘ # 匹配该字符串的正则表达式,使用了圆括号进行分组
# 分组内容可以通过正则中的方法提取出来
(?...)
(?:[a-zA-Z0-9]+\.) # (?:regex) 匹配不会保存下来供后续的使用和索引
(?#aaa) # (?#...) 此处不做匹配只做注释
(?=.com) # 如果一个字符串后面跟的是‘.com‘才做匹配
(?!.com) # 如果一个字符串不是后面跟‘.com‘才做匹配
(?<800-) # 如果字符串之前为‘800-‘才做匹配
(?<!192) # 如果字符串之前不为‘192‘才做匹配
(?(1)y|x) # 如果一个匹配组1存在,就与y匹配;否则,就与x匹配
my_str_1 = r‘1993-08‘
regex_1 = r‘([0-9]{4})-([0-9]{2})‘
res = re.match(regex_1, my_str_1)
print(res.groups()) # (‘1993‘, ‘08‘)
(?:)
拓展regex_2 = r‘(?:[0-9]{4})-([0-9]{2})‘
res = re.match(regex_2, my_str_1)
print(res.groups()) # (‘08‘,)
(?#)
拓展regex_2 = r‘([0-9]{4})-(?#[0-9]{2})‘
res = re.match(regex_2, my_str_1)
print(res.groups()) # (‘1993‘,)
(?=...)
拓展
my_str_1 = ‘www.baidu.com‘
my_str_2 = ‘www.github.io‘
regex_1 = r‘www\.(.*)\.(.*)‘
regex_2 = r‘www\.(.*)(?=\.com)\.(.*)‘
print(re.match(regex_1, my_str_1), re.match(regex_1, my_str_2)) # 都能匹配上
print(re.match(regex_2, my_str_1), re.match(regex_2, my_str_2)) # 第二个没有匹配成功
(?<=...)
拓展
my_str_1 = ‘800-277‘
my_str_2 = ‘900-277‘
regex_1 = r‘[0-9]{3,}-([0-9]*)‘
regex_2 = r‘[0-9]{3,}-(?<=800-)([0-9]*)‘
print(re.match(regex_1, my_str_1).groups()) # (‘277‘,)
print(re.match(regex_2, my_str_1).groups()) # (‘277‘,)
print(re.match(regex_1, my_str_2).groups()) # (‘277‘,)
print(re.match(regex_2, my_str_2)) # None
my_str_1 = ‘1abc2‘
my_str_2 = ‘abcabc‘
regex = ‘(?P<name>[0-9]*)abc(?(name)[0-9]*|abc)‘
print(re.match(regex, my_str_1))
print(re.match(regex, my_str_2).groups())
两个概念
regex object
)regex match object
)编译正则表达式(编译还是不编译?)
python代码是被先编译成字节码,然后在解释器执行。
指定eval()
或者exec()
调用一个代码对象,性能会有明显的提升。
正则预编译
re.compile()
能够提供预编译功能。purge()
函数可以清除这些缓存。匹配对象
成功调用match或者search返回的对象,匹配对象主要有两个方法:group()和groups()
group
要么返回整个对象,要么根据要求返回特定的子组。没有子组的要求,任然返回整个匹配。
groups
仅仅返回一个唯一或者全部子组的元组。没有子组的要求,返回空元组。
###### 源码参考
def match(pattern, string, flags=0):
"""尝试从字符串起始处匹配模式,成功返回一个匹配对象,失败返回None"""
return _compile(pattern, flags).match(string)
regex object
)方法##### 匹配成功时
m = re.match(‘foo‘, ‘foo‘)
# m 是一个匹配对象
if m is not None:
print(m.group()) # foo
##### 匹配失败时
m = re.match(‘foo‘, ‘bar‘)
# m 是一个匹配对象
if m is not None:
print(m.group()) #
##### 匹配长字符串
m = re.match(‘foo‘, ‘food in table‘)
if m is not None:
print(m.group) # foo
pos
和endpos
指定目标字符串的搜索范围。##### 源码参考
def search(pattern, string, flags=0):
"""从左至右严格搜索 模式 在字符串中的匹配,匹配成功返回一个匹配对象,否则就返回None"""
return _compile(pattern, flags).search(string)
"""
对比match和search
:match开头不匹配,停止匹配返回None
"""
m = re.match(‘foo‘, ‘seafood‘)
if m is not None:
print(m.group())
else:
print(‘没有搜索到‘)
# 输出结果 没有搜索到
m = re.search(‘foo‘, ‘seafood‘)
if m is not None:
print(m.group())
else:
print(‘没有搜索到‘)
# 输出结果 foo
在写匹配模式的时候使用择一匹配符 |
。
pattern = ‘bat|blt|bnt‘
m = re.match(pattern, ‘bat‘)
if m is not None:
print(m.group())
else:
print(‘没有匹配成功‘)
# 匹配成功 返回 bat
m = re.match(pattern, ‘bzt‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 匹配失败
.
号不能匹配换行符 \n
和空字符串pattern = ‘.end‘
m = re.match(pattern, ‘bend‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 匹配成功 返回bend
pattern = ‘.end‘
m = re.match(pattern, ‘end‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# . 号不匹配空字符串 匹配失败
pattern = ‘.end‘
m = re.match(pattern, ‘\nend‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# . 号不匹配换行符,匹配失败
pattern = ‘.end‘
m = re.search(pattern, ‘in the end.‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 匹配成功 返回‘ end’
pattern = ‘\.end‘
m = re.search(pattern, ‘in the .end‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 匹配成功 返回‘.end’
[]
与择一选择符 |
html
中数据<p>电影名称:<span>杀破狼</span>演员:<span>吴京</span></p>
import re
my_str = ‘<p>电影名称:<span>杀破狼</span>演员:<span>吴京</span></p>‘
pattern = ‘<p>电影名称:<span>(.*)</span>演员:<span>(.*)</span></p>‘
m = re.match(pattern, my_str)
if m is not None:
print(m.groups()) # 返回一个元组 (‘杀破狼‘, ‘吴京‘)
print(m.group()) # group 返回的是一个匹配对象
print(m.group(1)) # 拿到第一个分组的内容 杀破狼
print(m.group(2)) # 拿到第二个分组的内容 吴京
else:
print(‘没有匹配到!‘)
^
起始符$
结尾符\b
边界\B
非边界# 起始符 匹配成功过返回 the
m = re.search(‘^the‘, ‘the end‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 结尾符 匹配失败 字符串不是以 the 结尾
m = re.search(‘the$‘, ‘the end‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 边界符 \b 匹配成功 返回end
m = re.search(r‘\bend‘, ‘the end time‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
# 非边界符 \B 匹配失败 字符串中的end是单词边界
m = re.search(r‘\Bend‘, ‘the end time‘)
if m is not None:
print(m.group())
else:
print(‘匹配失败‘)
r‘\bend‘
才导致模式匹配没有歧义,如果忘记使用原始字符串,匹配结果可能会和预期不符合。findall()
和finditer()
查找每一次出现的位置findall()
print(re.findall(‘car‘, ‘car‘)) # [‘car‘]
print(re.findall(‘car‘, ‘carry me by the car‘)) # [‘car‘, ‘car‘]
print(re.findall(‘car‘, ‘no case‘)) # []
findall()
搭配子组使用
my_str = ‘<p>电影名称:<span>杀破狼</span>演员:<span>吴京</span></p>‘
pattern = ‘<p>电影名称:<span>(.*)</span>演员:<span>(.*)</span></p>‘
print(re.findall(pattern, my_str)) # [(‘杀破狼‘, ‘吴京‘)]
finditer()
findall()
类似,但是更节约内存的变体。s = ‘this and that.‘
pattern = r‘(th\w+) and (th\w+)‘
re.findall(pattern, s) # [(‘this‘, ‘that‘)]
re.finditer(pattern, s) # <callable_iterator object at 0x0000023D17765160>
next(re.finditer(pattern, s)).group(1) # this
new_list = [g.groups() for g in re.finditer(pattern, s)] # [(‘this‘, ‘that‘)]
finditer()
返回的是一个可迭代对象pos
和endpos
指定目标字符串的搜索范围。sub()
和 subn()
搜索与替换subn()
还返回一个表示替换的总数,返回一个元组 (替换后的字符串, 替换总数)
sub|subn(pattern, repl, string, count=0, flags=0)
"""
:pattern 正则表达式
:repl 替换的部分
:string 需要被替换的字符串
"""
pattern = ‘[0-9]‘
rpl = ‘x‘
my_str = ‘我的电话是15502732718‘
res = re.sub(pattern, rpl, my_str)
print(res) # 我的电话是xxxxxxxxxxx
res = re.subn(pattern, rpl, my_str)
print(res) # (‘我的电话是xxxxxxxxxxx‘, 11)
# 将 20/06/2020 改写成 2020/06/20
my_str = ‘20/06/2020‘
pattern = r‘(\d{2})/(\d{2})/(\d{4})‘
rpl = r‘\3/\2/\1‘
res = re.sub(pattern, rpl, my_str)
print(res) # 2020/06/20
split()
分隔字符串MAX
参数设定一个值指定最大分割数。split(pattern, string, maxsplit=0, flags=0):
"""
根据出现的模式拆分字符串,返回包含结果字符串的列表。在模式中使用()捕获子组,捕获的子组也会作为结果的一部分返回,如果限制字符串次数,则会按照指定次数分割,其余部分作为最后一个元素返回。
:pattern 模式(正则表达式)
:string 需要分割的字符串
:maxsplit 最大分割次数
"""
my_str = ‘str1:str2:str3‘
patterns = ‘:‘
re.split(patterns, my_str) # [‘str1‘, ‘str2‘, ‘str3‘]
re.split(patterns, my_str, 1) # [‘str1‘, ‘str2:str3‘]
my_str = ‘str1:str2:str3‘
patterns = ‘(:)‘
print(re.split(patterns, my_str)) # [‘str1‘, ‘:‘, ‘str2‘, ‘:‘, ‘str3‘]
print(re.split(patterns, my_str, 1)) # [‘str1‘, ‘:‘, ‘str2:str3‘]
(?i)
忽略大小写, re.I
my_str = ‘yes, Yes! YES?‘
patterns = r‘(?i)yes‘
re.findall(patterns, my_str) # [‘yes‘, ‘Yes‘, ‘YES‘]
(?m)
多行匹配,而不是将整个字符串视为单个实体。 re.M
my_str ="""
this is a pig,
that why we shout!
there is nothing!
"""
patterns = ‘(?m)^th.*‘
re.findall(patterns, my_str)
# [‘this is a pig,‘, ‘that why we shout!‘, ‘there is nothing!‘]
(?s)
该标记表明 .
号能够表示 \n 符号。 re.S
my_str = """
this is first line
this is second line
this is third line
"""
patterns = ‘th.+‘
re.findall(patterns, my_str)
# [‘this is first line‘, ‘this is second line‘, ‘this is third line‘]
my_str = """
this is first line
this is second line
this is third line
"""
patterns = ‘(?s)th.+‘
print(re.findall(patterns, my_str))
# [‘this is first line\nthis is second line\nthis is third line\n‘]
(?x)
允许用户通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜杠转义中)来创建易读的正则表达式。
例如匹配 (800) 555-1212
想提取中的三组数值
my_str = ‘(800) 555-1212‘
patterns = r"""(?x)
\((\d{3})\) # 800
[ ] # 空格
(\d{3}) # 555
- # -
(\d{4}) # 1212
"""
print(re.search(patterns, my_str).groups())
# (‘800‘, ‘555‘, ‘1212‘)
(?P<name>)
和 (?P=name)
前者通过名称标识符而不是使用从1到N的增量数字保存匹配,不使用名称标识符,则通过数字来检索。
通过 \g<name>
取出对应的值
my_str = ‘800 277-1212‘
pattern = r‘(?P<区号>\d{3}) (?P<前缀>\d{3})-(?:\d{4})‘
rpl = ‘(\g<区号>) \g<前缀>-xxxx‘
re.sub(pattern, rpl, my_str) # (800) 277-xxxx
? 后者可以在一个相同的正则表达式中重用模式。
在测试中目前为止都是失败的
标签:gic 多次 数值 搜索 忽略 加强 purge imp name
原文地址:https://www.cnblogs.com/raoqinglong/p/13232999.html