Python编程
Python 包含一个用于在字符串上处理正则表达式的模块。有关编写正则表达式以及不特定于 Python 的语法的更多信息,请参阅正则表达式 Wikibook。Python 的正则表达式语法类似于 Perl。
要在 Python 脚本中使用正则表达式,首先导入 "re" 模块:
import re
概述
Python 中的正则表达式函数一览:
import re
if re.search("l+", "Hello"): print(1) # 子字符串匹配足够
if not re.match("ell.", "Hello"): print(2) # 字符串开头必须匹配
if re.match(".el", "Hello"): print(3)
if re.match("he..o", "Hello", re.I): print(4) # 不区分大小写的匹配
print(re.sub("l+", "l", "Hello")) # 打印 "Helo"; 替换,即替换操作
print(re.sub(r"(.*)\1", r"\1", "HeyHey")) # 打印 "Hey"; 反向引用
print(re.sub("EY", "ey", "HEy", flags=re.I))# 打印 "Hey"; 不区分大小写的替换
print(re.sub(r"(?i)EY", r"ey", "HEy")) # 打印 "Hey"; 不区分大小写的替换
for match in re.findall("l+.", "Hello Dolly"):
print(match) # 打印 "llo" 和 "lly"
for match in re.findall("e(l+.)", "Hello Dolly"):
print(match) # 打印 "llo"; 匹配组 1
for match in re.findall("(l+)(.)", "Hello Dolly"):
print(match[0], match[1]) # 组结束时作为元组中的项
match = re.match("(Hello|Hi) (Tom|Thom)", "Hello Tom Bombadil")
if match: # 等同于 if match is not None
print(match.group(0)) # 打印整个匹配,忽略分组
print(match.group(1) + match.group(2)) # 打印 "HelloTom"
匹配与搜索
正则表达式的一个常见用途是从字符串中提取一部分或测试字符串中是否存在某个模式。Python 提供了几个函数来实现这一点。
match
和 search
函数做的几乎是相同的事情,不同之处在于,match
函数只有在模式匹配字符串开头时才会返回结果,而 search
会在字符串中的任何位置找到匹配。
>>> import re
>>> foo = re.compile(r'foo(.{,5})bar', re.I + re.S)
>>> st1 = 'Foo, Bar, Baz'
>>> st2 = '2. foo is bar'
>>> search1 = foo.search(st1)
>>> search2 = foo.search(st2)
>>> match1 = foo.match(st1)
>>> match2 = foo.match(st2)
在这个例子中,match2
将返回 None
,因为 st2
字符串并没有以给定模式开始。其他 3 个结果将是 Match
对象(见下文)。
你也可以在不编译正则表达式的情况下进行匹配和搜索:
>>> search3 = re.search('oo.*ba', st1, re.I)
这里我们直接使用了 re
模块的 search
函数,而不是使用模式对象的方法。对于大多数情况,最好先编译表达式。如果表达式使用多次,先编译会更高效,并使代码看起来更清晰。
编译后的模式对象函数还可以设置开始和结束搜索的位置,以便在给定字符串的子字符串中进行搜索。如果我们这样做:
>>> match3 = foo.match(st2, 3)
它会有效,因为我们告诉它从字符串的第 3 个字符开始搜索。
如果我们想搜索模式的多个实例,那么有两种选择。我们可以使用 search
和 match
函数的起始和结束位置参数,通过循环获取上一个匹配对象的位置(见下文),或者可以使用 findall
和 finditer
函数。findall
函数返回匹配字符串的列表,适用于简单搜索。对于稍微复杂的情况,应该使用 finditer
函数,它返回一个迭代器对象,在循环中使用时会生成 Match
对象。例如:
>>> str3 = 'foo, Bar Foo. BAR FoO: bar'
>>> foo.findall(str3)
[', ', '. ', ': ']
>>> for match in foo.finditer(str3):
... match.group(1)
...
', '
'. '
': '
如果你要迭代搜索结果,使用 finditer
函数几乎总是更好的选择。
匹配对象
Match
对象由 search
和 match
函数返回,包含有关模式匹配的信息。
group
函数返回对应于正则表达式中捕获组(用 ()
包裹的部分)的字符串,或者如果未给出组号,则返回整个匹配。使用我们上面定义的 search1
变量:
>>> search1.group()
'Foo, Bar'
>>> search1.group(1)
', '
捕获组也可以使用特殊语法赋予字符串名称,并通过 matchobj.group('name')
引用它们。对于简单的表达式,这通常是不必要的,但对于更复杂的表达式,它会非常有用。
你还可以使用 start
和 end
函数获取匹配或某个组在字符串中的位置:
>>> search1.start()
0
>>> search1.end()
8
>>> search1.start(1)
3
>>> search1.end(1)
5
这将返回整个匹配的起始和结束位置,以及第一个(在这个例子中唯一的)捕获组的起始和结束位置。
替换
正则表达式的另一个用途是替换字符串中的文本。要在 Python 中执行此操作,使用 sub
函数。
sub
最多接受 3 个参数:替换的文本、要替换的文本以及可选的最大替换次数。与匹配和搜索函数不同,sub
返回一个字符串,包含进行替换后的文本。
>>> import re
>>> mystring = 'This string has a q in it'
>>> pattern = re.compile(r'(a[n]? )(\w) ')
>>> newstring = pattern.sub(r"\1'\2' ", mystring)
>>> newstring
"This string has a 'q' in it"
此操作将任何前面有 "a" 或 "an" 的单一字母数字字符(\w
)用单引号括起来。替换字符串中的 \1
和 \2
是对表达式中 2 个捕获组的反向引用;这些就是在 search
中的 group(1)
和 group(2)
。
subn
函数与 sub
类似,不同之处在于它返回一个元组,包括结果字符串和替换次数。使用之前的字符串和表达式:
>>> subresult = pattern.subn(r"\1'\2' ", mystring)
>>> subresult
("This string has a 'q' in it", 1)
分割
split
函数根据给定的正则表达式分割字符串:
>>> import re
>>> mystring = '1. First part 2. Second part 3. Third part'
>>> re.split(r'\d\.', mystring)
['', ' First part ', ' Second part ', ' Third part']
转义
escape
函数会转义字符串中的所有非字母数字字符。这在你需要处理一个可能包含正则表达式元字符(如 (
和 .
)的未知字符串时非常有用,用于创建正则表达式。
>>> re.escape(r'This text (and this) must be escaped with a "\" to use in a regexp.')
'This\\ text\\ \\(and\\ this\\)\\ must\\ be\\ escaped\\ with\\ a\\ \\"\\\\\\"\\ to\\ use\\ in\\ a\\ regexp\\.'
标志
正则表达式使用的不同标志:
缩写 | 完整名称 | 描述 |
---|---|---|
re.I | re.IGNORECASE | 使正则表达式不区分大小写 |
re.L | re.LOCALE | 根据当前的区域设置影响某些特殊序列(\w, \W, \b, \B, \s, \S) |
re.M | re.MULTILINE | 使 ^ 和 $ 匹配每行的开始和结束,而不仅仅是字符串的开始和结束 |
re.S | re.DOTALL | 使 . 匹配所有字符,包括换行符 |
re.U | re.UNICODE | 使 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性 |
re.X | re.VERBOSE | 忽略空格,除非在字符类中或前面没有转义的反斜杠时,并且忽略 # 后面的所有内容 |
模式对象
如果你在程序中多次使用相同的正则表达式,或者只是希望将正则表达式分开管理,你应该创建一个模式对象,并在后续的搜索/替换中引用它。
创建模式对象,使用 compile
函数:
import re
foo = re.compile(r'foo(.{,5})bar', re.I + re.S)
第一个参数是模式,匹配字符串 "foo" 后跟最多 5 个任意字符,然后是 "bar",将中间的字符存储为一个组,稍后会讨论。第二个可选参数是标志,用来修改正则表达式的行为。标志本身是引用正则表达式引擎使用的整数的变量。在其他语言中,这些将是常量,但 Python 没有常量。如果需要标志,最好使用 compile
函数创建一个模式对象。