09 正则表达式
9.2 python中的正则表达式
-
re
模块提供的主要函数是search
. 它的目的是接受一个正则表达式(针) 和 一个字符串(草堆),并返回发现的第一个匹配(match
对象),或者None
import re res = re.search(r"fox", "the quick brown fox jumped...") print(res) # <_sre.SRE_Match object; span=(16, 19), match='fox'> # group() 方法返回一个包含匹配文本的字符串 print(res.group())
-
多个匹配
-
re.findall()
返回一个列表import re res = re.findall(r"o", "the quick brown fox jumped...fox") print(res) # ['o', 'o', 'o']
-
re.finditer()
返回一个生成器import re res = re.finditer(r"o", "the quick brown fox jumped...fox") print(res) # <callable_iterator object at 0x000001EC7D02BDA0>
-
9.3 基本正则表达式
-
字符组:允许指定一个字符应该与一组可能出现的字符之一,而不仅仅是一个单独字符匹配;可以使用
[]
并在方括号内累出所有可能的字符从而表示一个字符组re.search(r"[Pp]ython", "Python3") re.search(r"gr[ae]y", "gray") re.search(r"gr[ae]y", "grey")
-
区间
[0-9]
[a-z]
或[a-zA-Z]
[A-Za-z0-9\-_]
\
代表转义
-
取反
^
-
快捷方式 对应取反快捷方式
\W \D \S \B
-
\w
与任意一个单词字符匹配 -
\d
匹配数字字符res = re.search(r"\d", "the quick brown 12fox jumped...fox321") print(res) res = re.findall(r"\d", "the quick brown 12fox jumped...fox321") print(res)
-
\s
匹配空白字符, 比如空白、tab、换行 -
\b
匹配一个长度为0
的子串res = re.search(r"\bcorn\b", "corn") print(res)
-
.
匹配任意一个字符(\n
无法匹配)res = re.search(r"p....n", "python 3") print(res)
-
-
指定字符串的开始和结束
# ^ 指定字符串的开始 res = re.search(r"^python", "python 3") print(res) # $ 指定字符串的结尾 res = re.search(r"python$", "this code is python") print(res)
-
-
可选字符
-
?
符号指定一个字符、字符组或其他基本单元可选;允许该字符出现零次或一次# "honou?r" 允许u 出现或者不出现 res = re.findall(r"honou?r", "He served with honor and honour") print(res) # ['honor', 'honour']
-
-
重复
-
重复次数:
{N}
指定一个标记必须重复给定次数,N个字符与标记应该重复的次数对应。res = re.search(r"[\d]{3}-[\d]{4}", "867-5309 / Jerry") print(res) # <_sre.SRE_Match object; span=(0, 8), match='867-5309'>
-
重复区间:
{M,N}
M是下界,N是上界# 正则表达式是“贪心”的,尽可能多的匹配字符 res = re.search(r"[\d]{3,4}", "0421") print(res) # <_sre.SRE_Match object; span=(0, 4), match='0421'> res = re.search(r"[\d]{3,4}", "042") print(res) # <_sre.SRE_Match object; span=(0, 3), match='042'>
# 在重复操作符后加`?`,会导致重复被认为是“惰性” res = re.search(r"[\d]{3,4}?", "0421") print(res) # <_sre.SRE_Match object; span=(0, 3), match='042'>
-
开闭区间:
{1,}
用于指定出现1次或多次,没有上界res = re.search(r"[\d]{1,}", "0421") print(res) # <_sre.SRE_Match object; span=(0, 4), match='0421'>
-
-
速写
-
+
字符代替{1,}
(1个或多个);*
字符代替{0,}
(0个或多个)res = re.search(r"[\d]+", "0421") print(res) # <_sre.SRE_Match object; span=(0, 4), match='0421'>
-
9.4 分组
-
使用
()
指定分组 -
group()
方法传递一个对应你希望的分组参数(编号默认从1开始)group(0)
零分组 返回一个单独分组
res = re.search(r"([\d]{3})-([\d]{4})", "867-5309/Jenny") print(res.group(1)) # 867 print(res.groups()) # ('867', '5309') print(res.group()) # res.group(0) 867-5309
- 接受任意区间的电话
- 第一节
(\+?1)?[ .-]
寻找任何形式的美国国家号码(+1
1
) - 第二节
\(?[\d]{3})\)?[ .-]
用于抓取区号;可选的连字符或空白 - 第三节
([\d]{3})[ .-]?([\d]{4})
7为电话号码
- 第一节
res = re.search(r"(\+?1)?[ .-]?\(?([\d]{3})\)?[ .-]?([\d]{3})[ .-]?([\d]{4})", "(213) 867-5309") print(res)
-
命名分组
?P<first_name>
res = re.search(r"(\+?1)?[ .-]?\(?([\d]{3})\)?[ .-]?(?P<first_name>[\d]{3})[ .-]?([\d]{4})", "(213) 867-5309") print(res.group()) print(res.groupdict()) # {'first_name': '867'}
-
引用已经存在的分组
-
可以使用
\N
回溯引用编号分组;\1
将会匹配第一个分组 或者$1
res = re.search(r"<([\w_-]+)>stuff</\1>", "<foo>stuff</foo>") print(res.group())
-
9.5 先行断言
-
先行断言:能够基于之后内容是否存在接受或拒绝一个匹配,而不是需要接下来的内容作为匹配的一部分。
# `n(?!e)` 会匹配final中的na;Python中的n;无法匹配jasmine;仅仅返回n res = re.search(r"n(?!e)", "final") print(res) # <_sre.SRE_Match object; span=(2, 3), match='n'> res = re.search(r"n(?!e)", "jasmine") print(res) # None res = re.search(r"n(?!e)", "Python") print(res) # <_sre.SRE_Match object; span=(5, 6), match='n'>
9.6 标记
-
不区分大小写
re.IGNORECASE
或re.I
-
res = re.search(r"python", "Python Is Awesome", re.I) print(res) # <_sre.SRE_Match object; span=(0, 6), match='Python'>
-
-
点匹配换行符
re.DOTALL
或re.S
-
res = re.search(r".+", "foo\nbar") print(res) # <_sre.SRE_Match object; span=(0, 3), match='foo'> res = re.search(r".+", "foo\nbar", re.S) print(res) # <_sre.SRE_Match object; span=(0, 7), match='foo\nbar'>
-
-
多行模式
re.MULTILINE
或re.M
-
# 导致仅能够匹配字符串开始`^`、结束`$`字符可以匹配字符串任意行的开始或结尾 res = re.search(r"^bar", "foo\nbar") print(res) # None res = re.search(r"^bar", "foo\nbar", re.M) print(res) # <_sre.SRE_Match object; span=(4, 7), match='bar'>
-
-
详细模式
re.VERBOSE
或re.X
-
导致所有空白(除了在字符组中)被忽略,包括换行
-
讲
#
字符当作注释字符expr = r"(?P<first_three>[\d]{3})-(?P<last_four>[\d]{4})" res = re.search(expr, "867-5309") print(res) # <_sre.SRE_Match object; span=(0, 8), match='867-5309'> expr1 = r"""(?P<first_three>[\d]{3}) # the first three digits - # A literal hyphen (?P<last_four>[\d]{4}) # The last four digits """ res = re.search(expr1, "867-5309", re.X) print(res) # <_sre.SRE_Match object; span=(0, 8), match='867-5309'>
-
-
调试模式
re.DEBUG
编译正则表达式将一些调试信息输出到sys.stderr
-
使用多个标记
re.S|re.M
-
内联标记
-
(?i)
等同于re.I
print(re.search(r"(?i)FOO", "foo").group()) # foo
-
9.7 替换
-
re.sub()
接受三个参数- 正则表达式
- 用于替换的字符串
\1\2\3\4
返回分组 - 被搜索的原始字符串
res = re.sub(r"(\+?1)?[ .-]?\(?([\d]{3})\)?[ .-]?([\d]{3})[ .-]?([\d]{4})", r"\1\2\3\4", "(213) 867-5309") print(res) # 2138675309
9.8 已编译的正则表达式
-
compile
返回一个已编译的正则表达式对象,该对象可以被重复使用res = regex.sub(r"(\2) \3-\4", "+1 213.867.5309") print(res) # (213) 867-530
-
发送的这两个值在返回的匹配独享的
pos
与endpos
属性可用regex = re.compile("[\d]+") res = regex.search("1 mile is equal to 5280 feet.", pos=2) print(res) # <_sre.SRE_Match object; span=(19, 23), match='5280'