正则表达式匹配的几个步骤:
1. 用 import re 导入正则表达式模块。
2.用 re.compile()函数创建一个 Regex 对象(记得使用原始字符串)。
3.向 Regex 对象的 search()方法传入想查找的字符串。它返回一个 Match 对象。
4.调用 Match 对象的 group()方法,返回实际匹配文本的字符串。
正则表达式匹配更多模式:
1. 利用括号分组:group() 和groups() 方法。
>>> phoneNumRegex = re.compile(r\'(\d\d\d)-(\d\d\d-\d\d\d\d)\') >>> mo = phoneNumRegex.search(\'My number is 415-555-4242.\') >>> mo.group(1) \'415 >>> mo.group(2) \'555-4242\' >>> mo.group(0) \'415-555-4242\' >>> mo.group() \'415-555-4242\' >>> mo.groups() (\'415\', \'555-4242\') >>> areaCode, mainNumber = mo.groups() >>> print(areaCode) 415 >>> print(mainNumber) 555-4242
>>> phoneNumRegex = re.compile(r\'(\(\d\d\d\)) (\d\d\d-\d\d\d\d)\')
>>> mo = phoneNumRegex.search(\'My phone number is (415) 555-4242.\')
>>> mo.group(1)
\'(415)\'
>>> mo.group(2)
\'555-4242\'
2. 用管道匹配多个分组: "|" 第一次出现的匹配文本将作为Match对象返回。
>>> heroRegex = re.compile (r\'Batman|Tina Fey\') >>> mo1 = heroRegex.search(\'Batman and Tina Fey.\') >>> mo1.group() \'Batman\' >>> mo2 = heroRegex.search(\'Tina Fey and Batman.\') >>> mo2.group() \'Tina Fey\'
>>> batRegex = re.compile(r\'Bat(man|mobile|copter|bat)\')
>>> mo = batRegex.search(\'Batmobile lost a wheel\')
>>> mo.group()
\'Batmobile\'
>>> mo.group(1)
\'mobile
3. 用问号实现可选匹配: "?" 不论这段文本在不在, 正则表达式
都会认为匹配
>>> batRegex = re.compile(r\'Bat(wo)?man\') >>> mo1 = batRegex.search(\'The Adventures of Batman\') >>> mo1.group() \'Batman\' >>> mo2 = batRegex.search(\'The Adventures of Batwoman\') >>> mo2.group() \'Batwoman\'
>>> phoneRegex = re.compile(r\'(\d\d\d-)?\d\d\d-\d\d\d\d\')
>>> mo1 = phoneRegex.search(\'My number is 415-555-4242\')
>>> mo1.group()
\'415-555-4242\'
>>> mo2 = phoneRegex.search(\'My number is 555-4242\')
>>> mo2.group()
\'555-4242
4. 用星号匹配零次或多次: "*"( 称为星号)意味着“匹配零次或多次”,即星号之前的分组
>>> batRegex = re.compile(r\'Bat(wo)*man\') >>> mo1 = batRegex.search(\'The Adventures of Batman\') >>> mo1.group() \'Batman\' >>> mo2 = batRegex.search(\'The Adventures of Batwoman\') >>> mo2.group() \'Batwoman\' >>> mo3 = batRegex.search(\'The Adventures of Batwowowowoman\') >>> mo3.group() \'Batwowowowoman
5.用加号匹配一次或多次: "+"则意味着“ 匹配一次或多次”
>>> batRegex = re.compile(r\'Bat(wo)+man\') >>> mo1 = batRegex.search(\'The Adventures of Batwoman\') >>> mo1.group() \'Batwoman\' >>> mo2 = batRegex.search(\'The Adventures of Batwowowowoman\') >>> mo2.group() \'Batwowowowoman\' >>> mo3 = batRegex.search(\'The Adventures of Batman\') >>> mo3 == None True
6.用花括号匹配特定次数: "{}"如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括
号包围的数字,除了一个数字,还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和
一个最大值.
>>> haRegex = re.compile(r\'(Ha){3}\') >>> mo1 = haRegex.search(\'HaHaHa\') >>> mo1.group() \'HaHaHa\' >>> mo2 = haRegex.search(\'Ha\') >>> mo2 == None True
贪心和非贪心匹配:
Python 的正则表达式默认是“ 贪心” 的,它们会尽
可能匹配最长的字符串,花括号的“ 非贪心” 版本匹配尽可能最短的字符串,即在
>>> greedyHaRegex = re.compile(r\'(Ha){3,5}\')
>>> mo1 = greedyHaRegex.search(\'HaHaHaHaHa\')
>>> mo1.group()
\'HaHaHaHaHa\'
>>> nongreedyHaRegex = re.compile(r\'(Ha){3,5}?\')
>>> mo2 = nongreedyHaRegex.search(\'HaHaHaHaHa\')
>>> mo2.group()
\'HaHaHa\'
findall() 和search() 方法:
search()方法: 返回一个 Match对象, 包含被查找字符串中的“ 第一次” 匹配的文本
>>> phoneNumRegex = re.compile(r\'\d\d\d-\d\d\d-\d\d\d\d\') >>> mo = phoneNumRegex.search(\'Cell: 415-555-9999 Work: 212-555-0000\') >>> mo.group() \'415-555-9999\'
findall()方法:返回一组
字符串, 包含被查找字符串中的所有匹配findall()不是返回一个 Match 对象, 而是返回一个字符串列表,
只要在正则表达式中没有分组。列表中的每个字符串都是一段被查找的文本, 它匹配该正则表达式。
>>> phoneNumRegex = re.compile(r\'\d\d\d-\d\d\d-\d\d\d\d\') # has no groups >>> phoneNumRegex.findall(\'Cell: 415-555-9999 Work: 212-555-0000\') [\'415-555-9999\', \'212-555-0000\']
如果在正则表达式中有分组, 那么 findall 将返回元组的列表
>>> phoneNumRegex = re.compile(r\'(\d\d\d)-(\d\d\d)-(\d\d\d\d)\') # has groups >>> phoneNumRegex.findall(\'Cell: 415-555-9999 Work: 212-555-0000\') [(\'415\', \'555\', \'1122\'), (\'212\', \'555\', \'0000\')]
字符分类
缩写字符分类 表示
\d 0 到 9 的任何数字
\D 除 0 到 9 的数字以外的任何字符
\w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W 除字母、数字和下划线以外的任何字符
\s 空格、制表符或换行符(可以认为是匹配“空白”字符)
\S 除空格、制表符和换行符以外的任何字符
字符分类[0-5]只匹配数字 0 到 5
>>> xmasRegex = re.compile(r\'\d+\s\w+\') >>> xmasRegex.findall(\'12 drummers, 11 pipers, 10 lords, 9 ladies, 8 maids, 7 swans, 6 geese, 5 rings, 4 birds, 3 hens, 2 doves, 1 partridge\') [\'12 drummers\', \'11 pipers\', \'10 lords\', \'9 ladies\', \'8 maids\', \'7 swans\', \'6 geese\', \'5 rings\', \'4 birds\', \'3 hens\', \'2 doves\', \'1 partridge\']
建立自己的字符分类:
1.字符分类[aeiouAEIOU]将匹配所有元音字符, 不论大小写
>>> vowelRegex = re.compile(r\'[aeiouAEIOU]\') >>> vowelRegex.findall(\'RoboCop eats baby food. BABY FOOD.\') [\'o\', \'o\', \'o\', \'e\', \'a\', \'a\', \'o\', \'o\', \'A\', \'O\', \'O\']
2.也可以使用短横表示字母或数字范围:字符分类[a-zA-Z0-9]将匹配所有小写字母、 大写字母和数字请注意,在方括号内,普通的正则表达式符号不会被解释字符分类将匹配
数字 0 到 5 和一个句点。你不需要将它写成[0-5.]
3.过在字符分类的左方括号后加上一个插入字符( ^), 就可以得到“ 非字符类”。
非字符类将匹配不在这个字符类中的所有字符。
>>> consonantRegex = re.compile(r\'[^aeiouAEIOU]\') >>> consonantRegex.findall(\'RoboCop eats baby food. BABY FOOD.\') [\'R\', \'b\', \'c\', \'p\', \' \', \'t\', \'s\', \' \', \'b\', \'b\', \'y\', \' \', \'f\', \'d\', \'.\', \' \', \'B\', \'B\', \'Y\', \' \', \'F\', \'D\', \'.\']
插入字符和美元字符:
1.可以在正则表达式的开始处使用插入符号( ^),表明匹配必须发生在被查找文本开始处。
2.可以再正则表达式的末尾加上美元符号( $),表示该字符串必须以这个正则表达式的模式结束。
>>> beginsWithHello = re.compile(r\'^Hello\') >>> beginsWithHello.search(\'Hello world!\') <_sre.SRE_Match object; span=(0, 5), match=\'Hello\'> >>> beginsWithHello.search(\'He said hello.\') == None True >>> endsWithNumber = re.compile(r\'\d$\') >>> endsWithNumber.search(\'Your number is 42\') <_sre.SRE_Match object; span=(16, 17), match=\'2\'> >>> endsWithNumber.search(\'Your number is forty two.\') == None True >>> wholeStringIsNum = re.compile(r\'^\d+$\') >>> wholeStringIsNum.search(\'1234567890\') <_sre.SRE_Match object; span=(0, 10), match=\'1234567890\'> >>> wholeStringIsNum.search(\'12345xyz67890\') == None True >>> wholeStringIsNum.search(\'12 34567890\') == None True
通配字符:
1.在正则表达式中,.(句点)字符称为“通配符”,句点字符只匹配一个字符。
>>> atRegex = re.compile(r\'.at\') >>> atRegex.findall(\'The cat in the hat sat on the flat mat.\') [\'cat\', \'hat\', \'sat\', \'lat\', \'mat\']
2.用点-星匹配所有字符( .*):
>>> nameRegex = re.compile(r\'First Name: (.*) Last Name: (.*)\') >>> mo = nameRegex.search(\'First Name: Al Last Name: Sweigart\') >>> mo.group(1) \'Al\' >>> mo.group(2) \'Sweigart\'
3. 点-星使用“贪心” 模式:它总是匹配尽可能多的文本。要用“非贪心” 模式匹配所有文本, 就使用点-星和问号
>>> nongreedyRegex = re.compile(r\'<.*?>\') >>> mo = nongreedyRegex.search(\'<To serve man> for dinner.>\') >>> mo.group() \'<To serve man>\' >>> greedyRegex = re.compile(r\'<.*>\') >>> mo = greedyRegex.search(\'<To serve man> for dinner.>\') >>> mo.group() \'<To serve man> for dinner.>\'
4. 用句点字符匹配换行
点-星将匹配除换行外的所有字符。通过传入 re.DOTALL 作为 re.compile()的第
二个参数, 可以让句点字符匹配所有字符, 包括换行字符
>>> noNewlineRegex = re.compile(\'.*\') >>> noNewlineRegex.search(\'Serve the public trust.\nProtect the innocent. \nUphold the law.\').group() \'Serve the public trust.\' >>> newlineRegex = re.compile(\'.*\', re.DOTALL) >>> newlineRegex.search(\'Serve the public trust.\nProtect the innocent.\nUphold the law.\').group() nUphold the law.\').group() \'Serve the public trust.\nProtect the innocent.\nUphold the law.\'
正则表达式符号总结:
?匹配零次或一次前面的分组。
*匹配零次或多次前面的分组。
+匹配一次或多次前面的分组。
{n}匹配 n 次前面的分组。
{n,}匹配 n 次或更多前面的分组。
{,m}匹配零次到 m 次前面的分组。
{n,m}匹配至少 n 次、至多 m 次前面的分组。
{n,m}?或*?或+?对前面的分组进行非贪心匹配。
^spam 意味着字符串必须以 spam 开始。
spam$意味着字符串必须以 spam 结束。
.匹配所有字符,换行符除外。
\d、 \w 和\s 分别匹配数字、单词和空格。
\D、 \W 和\S 分别匹配出数字、单词和空格外的所有字符。
[abc]匹配方括号内的任意字符(诸如 a、 b 或 c)。
[^abc]匹配不在方括号内的任意字符。
不区分大小写的匹配:
可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。
>>> robocop = re.compile(r\'robocop\', re.I) >>> robocop.search(\'RoboCop is part man, part machine, all cop.\').group() \'RoboCop\' >>> robocop.search(\'ROBOCOP protects the innocent.\').group() \'ROBOCOP\' >>> robocop.search(\'Al, why does your programming book talk about robocop so much?\').group() \'robocop
用sub()方法替换字符串: