正则表达式初探

2018-12-07  本文已影响0人  SimonJoe246

正则表达式

字符串是编程时遇到的最多的一种数据结构,比如判断一个电子邮件地址或一个座机号码是否符合格式要求,虽然我们可以提取 @ 前后的字符串,再分别判断单词和域名,但这样代码十分复杂, 而且难以复用。

这时,我们可以

正则表达式(Regulation Expression)是一种文本模式,包括普通字符(例如,a 到 z之间的字母,数字)和特殊字符(称为元字符,具有图书意义的字符,如 +表示其前导字符至少出现1次,$*()

基本用法

正则表达式本身也是个字符串,怎么用字符描述字符呢?这就是我们这篇文章要讲的主要内容。

直接给出字符,就是精确匹配:

\d 表示一个数字

\w 表示一个字母或数字

. 表示任意字符,若要表示 . 英文句号,需要加转义字符 \.

因此:

00\d 可以匹配 003004,但无法匹配 00A

\w\w\w 可以匹配 010

py. 可以匹配 pyapy3py!

怎么匹配变长字符串:

所以,\d{3}\s+\d{3,8} 可以匹配任意用空格隔开的带区号的电话号码

但是,以上方法匹配 010 - 2569888 还是不可以的,需要正则的高级用法

进阶

当有多种类型字符选择时,如数字、字母、大小写,可以用 [] 来将其包括进去

^$有什么作用,py 是可以匹配 python的,但 ^py$ 就只能匹配 py

python的 re 模块

python 内置了 re 正则模块,

现在尝试写一个正则表达式以验证 Email 地址:

Email 地址格式要求:

name@domain

name最长64,domain最长253,总长最长256

name可以使用任意ASCII字符:

但是有些邮件服务器会拒绝包含有特殊字符的邮件地址

domain仅限于26个英文字母、10个数字、连词号-

连词号-不能是第一个字符

顶级域名(com、cn等)长度为2到6个

代码如下:

>>> r = r'^[a-zA-Z]+[\.\_]?[a-zA-Z0-9]+@[a-zA-Z0-9]([\_]?[a-zA-Z0-9]+)*\.[a-zA-Z]{2,6}(\.[a-zA-Z]{2})?$'
>>> re.match(r, 'simonkindle@126.com')
<_sre.SRE_Match object; span=(0, 19), match='simonkindle@126.com'>
>>> re.match(r, 'simonkindle@126.com.cn')
<_sre.SRE_Match object; span=(0, 22), match='simonkindle@126.com.cn'>
>>> re.match(r, 'simonkindle@126.com.cn.cn')

贪婪匹配

*+ 都是贪婪匹配的,即在符合格式要求的情况下尽可能多地匹配文字。如果想取消贪婪匹配,在它们后面加上一个 ? 即可。

具体看下面例子:

>>> todo = `<H1>Chapter 1 - 介绍正则表达式</H1>`
>>> r = '<.*>'
>>> re.match(r, todo)
<_sre.SRE_Match object; span=(0, 28), match='<H1>Chapter 1 - 介绍正则表达式</H1>'>
>>> r = '<.*?>'
>>> re.match(r, todo)
<_sre.SRE_Match object; span=(0, 4), match='<H1>'>

前者贪婪匹配,匹配 <> 之间尽可能多的字符,后者非贪婪匹配,匹配 <> 之间尽可能少的字符。

切分字符串

正则表达式还可以用来切分字符串,如何将以不定数空格分割的单词提取出来?

>>> s = 'a  b fef   v'
>>> s.split(' ')
['a', '', 'b', 'fef', '', '', 'v']

无法识别连续空格

>>> r = '[\s]+'
>>> re.split(r, s)
['a', 'b', 'fef', 'v']

分组

正则表达式还有提取子字符串的功能。用 () 表示的就是要提取的分组(Group)。

>>> r = '^(\d{3})-(\d{3,8})$'
>>> m = re.match(r, '022-22820279')
>>> m.groups()
('010', '22820279')
>>> m[0]
'010-22820279'
>>> m[1]
'010'
>>> m[2]
'22820279'
>>> m[3]

group(0)永远是原字符串,之后依次是括号中的字串

编译

当我们在 python 中使用正则表达式时,re 模块会在背后干这样两件事:

如果我们使用的正则表达式要匹配上千次,每次都要编译会浪费大量时间。出于效率考虑,我们可以预编译该表达式,这样以后匹配就省去这个步骤了

>>> r = re.compile('^(\d{3})-(\d{3,8})$')
>>> r.match('010-22820279')
<_sre.SRE_Match object; span=(0, 12), match='010-22820279'>
>>> r.match('010-22820279').groups()
('010', '22820279')
上一篇 下一篇

猜你喜欢

热点阅读