Python的 re 模块:核心函数和方法
1. 使用 compile()函数编译正则表达式
导入 re 模块后,在compile() 中编译正则表达式,例如:pattern = re.compile('正则表达式',re.S),然后就可以使用pattern来进行匹配了。
在compile 中还可以带模块属性,即re.S,re.I,re.L,re.M,re.X等。
2.匹配对象以及 group()和 groups()方法
匹配对象有两个主要的方法:group()和 groups()。 调用 match()或者 search()返回的对象就是匹配对象,group()要么返回整个匹配对象,要么根据要求返回特定子组。
groups()则仅返回一个包含唯一或者全部子组的元组。如果没有子组的要求,那么当group()仍然返回整个匹配时,groups() 返回一个空元组。
3. 使用 match()方法匹配字符串
match() 函数试图从字符串的起始部分对模式进行匹配。如果匹配成功,就返回一个匹配对象;如果匹配失败,就返回 None,匹配对象的 group()方法能够用于显示那个成功的匹配。
1 html = '<html><head>title</head><body>2333</body></html>' 2 pattern = re.compile('<.*?head>(.*?)<.*?body>(.*?)<.*?>') 3 4 m = re.match(pattern, html) 5 6 print(m.group()) 7 print(m.group(1)) 8 print((m.group(2))) 9 print(m.groups()) 10 # 输出: 11 # <html><head>title</head><body>2333</body> 12 # title 13 # 2333
14 # ('title', '2333')
>>> re.match('foo', 'food on the table').group() 'foo'
4. 使用 search()在一个字符串中查找模式,(搜索)
search()的工作方式与 match()完全一致,不同之处在于 search()会用它的字符串参数,在任意位置对给定正则表达式模式搜索第一次出现的匹配情况。
如果搜索到成功的匹配,就会返回一个匹配对象;否则,返回 None。
search() 和 match() 不同之处在于,search() 会搜索字符串中间部分。
>>> m = re.match('foo', 'seafood') # 匹配失败 >>> m = re.search('foo', 'seafood') # 使用 search() 代替 >>> if m is not None: m.group() ... 'foo' # 搜索成功,但是匹配失败,在seafood中搜索foo
5.重复、特殊字符以及分组
用一个匹配电子邮件地址的正则表达式做例子。(w+@w+.com),这个正则表达式只能匹配简单的地址。
为了在域名前添加主机名称支持,例如 www.xxx.com,需要使用?,w+@(w+.)?w+.com,让(w+.)可选。
>>> pattern = 'w+@(w+.)?w+.com' >>> re.match(pattern, 'nobody@xxx.com').group() 'nobody@xxx.com' >>> re.match(pattern, 'nobody@www.xxx.com').group()
'nobody@www.xxx.com'
进一步扩展该示例,允许任意数量的中间子域名存在。把?改为 * 号。w+@(w+.)*w+.com
>>> patt = 'w+@(w+.)*w+.com' >>> re.match(patt, 'nobody@www.xxx.yyy.zzz.com').group()
'nobody@www.xxx.yyy.zzz.com'
使用圆括号来匹配和保存子组,以便于后续处理。
>>> m = re.match('(www)-(ddd)', 'abc-123') >>> m.group() # 完整匹配 'abc-123' >>> m.group(1) # 子组 1 'abc' >>> m.group(2) # 子组 2 '123' >>> m.groups() # 全部子组 ('abc', '123')
group()通常用于以普通方式显示所有的匹配部分,但也能用于获 取各个匹配的子组。可以使用 groups()方法来获取一个包含所有匹配子字符串的元组。
6.使用 sub()和 subn()搜索与替换
有两个函数/方法用于实现搜索和替换功能:sub()和 subn()。两者几乎一样,都是将某字符串中所有匹配正则表达式的部分进行某种形式的替换。
用来替换的部分通常是一个字符串, 但它也可能是一个函数,该函数返回一个用来替换的字符串。
subn()和 sub()的不同点是subn() 还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
>>> re.sub('X', 'Mr. Smith', 'attn: X Dear X, ') 'attn: Mr. Smith 12 12Dear Mr. Smith, 12' >>> >>> re.subn('X', 'Mr. Smith', 'attn: X Dear X, ') ('attn: Mr. Smith 12 12Dear Mr. Smith, 12', 2) >>> >>> print(re.sub('X', 'Mr. Smith', 'attn: X Dear X, ')) attn: Mr. Smith Dear Mr. Smith, >>> re.sub('[ae]', 'X', 'abcdef') 'XbcdXf' >>> re.subn('[ae]', 'X', 'abcdef') ('XbcdXf', 2)
7.扩展符号
通过使用 (?iLmsux) 系列选项,用户可以直接在正则表达式里面指定一个或者多个标记,而不是通过 compile()或者其他 re 模块函数。
下面为一些使用 re.I/IGNORECASE 的示例, 最后一个示例在 re.M/MULTILINE 实现多行混合:
>>> re.findall(r'(?i)yes', 'yes? Yes. YES!!') # (?i) 不区分大小写 ['yes', 'Yes', 'YES'] >>> re.findall(r'(?i)thw+', 'The quickest way is through this tunnel.') ['The', 'through', 'this'] >>> re.findall(r'(?im)(^th[w ]+)', """ ... This line is the first, ... another line, ... that line, it's the best ... """) ['This line is the first', 'that line']