AUTOMATE THE BORING STUFF WITH PYTHON读书笔记 - 第7章:PATTERN MATCHING WITH REGULAR EXPRESSIONS

Regular Expression称为正则表达式,以下简称为RE。

不用RE在文本中查找模式

美国电话号码的格式为###-###-###,如果要判断号码格式是否合法,并且不用RE,需要结合isdecimal()方法。

def is_valid(phone_num):
    if(len(phone_num) != 12):
        return False

    if phone_num[3] != '-' and phone_num[7] != '-':
        return False

    for s in phone_num.split('-'):
        if not s.isdecimal():
            return False

    return True


print(is_valid('123-456-7890'))
print(is_valid('123-4#6-7890'))

如果要在一段文本中寻找电话号码,可以用msg[i:i+12]结合以上is_valid()函数。

通过RE在文本中寻找模式

RE在re模块中定义。因此需要import re

# 正则表达式\d表示数字字符
>>> regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
>>> phone_number = regex.search('My number is 415-555-4242.')
>>> print(phone_number) # 如果匹配,则返回Match对象
<_sre.SRE_Match object; span=(13, 25), match='415-555-4242'>
>>> print(phone_number.group()) # group返回匹配的字符串
415-555-4242
>>> print(phone_number.span())
(13, 25)

>>> phone_number = regex.search('My number')
>>> print(phone_number) # 如果不匹配,则返回None
None

交互式RE测试参见网站:https://pythex.org/

更多正则表达式

在正则表达式中,. ^ $ * + ? { } [ ] \ | ( )这些字符具有特殊含义,需要用\转义。
()表示group,例如(\d\d\d)-(\d\d\d-\d\d\d\d)
需要匹配多个group可以用管道符’|'分开,例如(patternA|patternB)
0个或1个匹配用?,0个或多个匹配用*,一个或多个匹配用+
固定次数的匹配用{n},例如{3},次数在某一区间使用{m,n}的格式,例如{3,5}
示例:

>>> re.compile(r'(\d\d\d)-(\d\d\d\d)').search('123-4567').group(2)
'4567'
>>> re.compile(r'(good|bad)man').search('goodman').group()
'goodman'
>>> re.compile(r'(good|bad)man').search('goodman').group(1)
'good'

如何引用group??? 是在替换中指定吗???

贪婪与非贪婪模式匹配

默认是贪婪模式,即最长的匹配;在}后面加?,可指定非贪婪模式。

>>> re.compile(r'(ha){3,5}').search('hahahahaha').group()
'hahahahaha'
>>> re.compile(r'(ha){3,5}?').search('hahahahaha').group()
'hahaha'

FINDALL()方法

search()只返回第一个匹配,findall()返回所有匹配,并返回一个list:

>>> re.compile(r'(\w+)').findall('good bye!')
['good', 'bye']
>>> re.compile(r'(\w+)').search('good bye!').group()
'good'

注意不要写成(\w)+

字符分类

\d表示数字字符,就是09\D表示非\d
\w表示数字,字母和下划线; \W表示非\w
\s表示space字符,包括空格,tab和换行;\S表示非\s

扫描二维码关注公众号,回复: 8916189 查看本文章

并非任何时候都需要group,也可以用[]表示可匹配其中任意字符,其中的-表示区间,|表示或者,^表示非。

>>> re.compile(r'[abc]').search('good bye!').group()
'b'
>>> re.compile(r'[a-z]').search('good bye!').group()
'g'
>>> re.compile(r'[a|b]').search('good bye!').group()
'b'
>>> re.compile(r'[d|b]').search('good bye!').group()
'd'
>>> re.compile(r'[^a-z]').search('goodbye6!').group()
'6'

制作自己的字符类

例如'[^aeiouAEIOU]表示元音。(\w+)表示单词。

脱字符和美元符

脱字符^表示行首,美元符$表示行末。

通配符

.称为通配符,可匹配任意单个字符。
.*默认匹配除换行符(\n)外的任意模式,不过可以指定re.DOTALL将换行符也计在内。

>>> re.compile(r'.*').search('row1\nrow2').group()
'row1'
>>> re.compile(r'.*', re.DOTALL).search('row1\nrow2').group()
'row1\nrow2'

正则表达式回顾

?, *+
{m}表示正好m次匹配;{m,n}表示m到n次匹配,m如省略表示0,n如省略表示无限。{}?表示非贪婪模式。
..*
\d, \w, \s; \D, \W, \S
[abc], [^abc], [abc|def]

大小写不敏感的匹配

默认是大小写敏感的,指定re.I标志为可实现大小写不敏感的匹配,例如re.compile(pattern, re.I)

用SUB()方法替换字符串

注意,可以用\n的形式引用第n个group。

>>> re.compile('(\d\d\d)-(\d\d\d\d)').sub(r'\1-****', '123-4567')
'123-****'
>>> re.compile('(\d\d\d)-(\d\d\d\d)').sub(r'\2-\1', '123-4567')
'4567-123'

管理复杂的正则表达式

当正则表达式较复杂,需要跨多行写时,可以指定编译的re.VERBOSE标志以及''',例如

re.compile(r'''(
	sub-pattern1
	sub-pattern2
	...
	sub-patternN
	)''', re.VERBOSE)

多种编译模式的组合

RE.IGNORECASE, RE.DOTALL和RE.VERBOSE都是bitmap,因此用|组合就好。

项目: 抽取电话号码和邮件地址

略。

发布了375 篇原创文章 · 获赞 43 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/stevensxiao/article/details/104101699