Python之re正则模块

时间:2022-01-21 18:54:14

正则表达式可以帮助我们更好的描述复制的文本格式,可以更好地利用它们对文本数据进行检索、替换、提取和修改操作。

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

http://docs.python.org/2.7/library/re.html#module-re

1、 re入门

第一步:先要引入有关正则表达式的包:

#-*- coding: utf-8 -*-
import re

第二步:使用指定的正则表达式构建一个正则表达式对象,下面正则是用来搜索长度为10的a-z的英文字母

#-*- coding: utf-8 -*-
import re
regex = re.compile(r'[a-z]{10}')

第三步:根据正则表达式指定数据中检索匹配项,如果匹配IsMatch方法就会返回true

#!/usr/bin/env python26
#-*- coding:utf-8 -*-
import re

regex = re.compile(r'[a-z]{10}') m1 = re.match(regex,'')
m2 = re.match(regex,'abcdefghij') if m1:
print "m1 match"
if m2:
print "m2 match"

2、三个重要的正则表达式命令

记住正则表达式最好的办法就是记住这三样东西:Bracket(括号)、caret(插入符号)、Dollars(美元符号)

B(括号)

在正则表达式中有3种类型的括号:

方括号"["和花括号"{"

方括号"["内是需要匹配的字符,花括号"{"内是指定匹配字符的数量

圆括号"("则是用来分组的

C(插入符号) 插入符号"^"表示正则表达式的开始  
D(美元符号) 美元符号"$"表示正则式的结束

3、验证

3.1 验证字符串

输入的字符在a-g之间:[a-g]

输入的字符在a-g之间并且长度为3:[a-g]{3}

输入的字符在a-g之间并且最大长度为3最小长度为1:[a-g]{1,3}

如何匹配像01234567那样的固定8位数:^[0-9]{8}$

如何验证最小长度为3最大长度为7的数字:^[0-9]{3,7}$

如何验证像LJI10201030那样的发票编号,前3个是字母剩余为8位长度的数字:^[A-Z]{3}[0-9]{8}$

不区分大小写:^[a-zA-Z]{3}[0-9]{8}$

 3.2 验证url

验证简单的网址URL格式吗?

第一步:检查是否存在www:^www.或者^[w]{3}.

第二步:域名必须是长度在1-15的英文字母:.[a-z]{1,15}

第三步:以.com或者.org结束:.(com|org)$

完整的表达式如下:

^www[.][a-z]{1,15}[.](com|org)$

3.3 验证Email

使用BCD(3条基本语法)如何验证email格式

第一步:email是长度在1-10的英文字母开头,最后跟一个“@”:

^[a-z][a-zA-Z0-9]{1,9}@$

第二步:@后面是长度在1-10的英文字母,后面跟一个".":

@[a-zA-Z]{1,10}.

第三步:最后以.com或者.org结束:

.(com|org)$

最后完整表达式:

^[a-z][a-zA-Z0-9]{1,9}@[a-zA-Z]{1,10}[.](com|org)$

 3.4 验证值在0-25的数字:

第一步:个位数[0-9]

第二步: 10-19表示[0-1][0-9]

第三步:20-25表示[0-2][0-5]

分为三组,组与组之间区分方式为小括号(,组与组之间的组合方式为|

^(([0-9])|([0-1][0-9])|([0-2][0-5]))$

 3.5 验证格式为MM/DD/YYYY,YYYY/MM/DD 和DD/MM/YYYY的日期

DD/MM/YYYY:
^(([1-9]|0[1-9])|[1-2][0-9]|3[0-1])[-./]([1-9]|0[1-9]|1[0-2])[-./](1[9][0-9]|2[0][0-9][0-9])$
步骤 正则表达式 描述说明

先检查DD。首先DD的长度为1-29(2月份),1-30(小月),1-31(大月)

匹配[1-9]|0[1-9]

[1-9]|0[1-9] 允许用户输入1-9或者01-09
再为DD添加匹配10-19 1[0-9] 允许用户输入10-19
再为DD添加匹配20-29 2[0-9] 允许用户输入20-29
判断30-31 3[0-1] 允许用户输入30-31
分隔符/ . -判断 [- . /] 日期分割符
判断MM [1-9]|0[1-9]|1[0-2] 允许用户输入1-9或者01-09以及10-12月
YYYY 1[9][0-9][0-9]|2[0][0-9][0-9] 允许用户输入1900-2099

4、字符串类

匹配一个电话区号码:'010-84451222 01084451222 (010)84451222'

首先是一个转义字符\(,它能出现0次或者1次?,然后是一个0,后面跟着2个数字\d{2},然后是)或者-或者空格中的一个[)- ],它出现1次或者不出现?,最后是8个数字\d{8}

完整的表达式为\(?0\d{2}[)- ]?\d{8}

#!/usr/bin/env python2.7
#-*- coding: utf8 -*- import re regex = re.compile(r'\(?0\d{2}[)-]?\d{8}') m1 = re.search(regex,'010-84451222')
m2 = re.search(regex,'')
m3 = re.search(regex,'(010)84451222') m4 = re.search(regex,'010-84451222 01084451222 (010)84451222') if m4 is not None:
print m4.group() m5 = re.findall(regex,'010-84451222 01084451222 (010)84451222') print m5

5、正则表达式符

5.1 常用的元字符

 代码     说明 
 . 匹配除换行符以外的任意字符       
 \w 匹配字母或数字或下划线或汉字  
 \s 匹配任意的空白符  
 \d 匹配数字  
 \b 匹配单词的开始或结束  
 ^  匹配字符串的开始  
 $  匹配字符串的结束  

5.2 常用的限定符

代码   说明
* 重复零次或更多次  
+ 重复一次或更多次    
? 重复零次或一次              
{n} 重复n次
{n,m} 重复n到m次
^:匹配字符串的开始
$:匹配字符串的结尾
\b:匹配一个单词的边界
\d:匹配任意数字
\D:匹配任意非数字字符
x?:匹配一个可选的x字符(它匹配1次或者0次x字符)
x*:匹配0次或者多次x字符
x+:匹配1次或者多次x字符
x{n,m}:匹配x字符,至少n次,至多m次
{a|b|c}:要么匹配a,要么匹配b,要么匹配c
(x):一般情况下表示一个记忆组

6、分支条件

那个表达式也能匹配010)12345678或者(022-12345678这样的不正确的格式。要解决这个问题,需要用到分支条件。

正则表达式里的分支条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。

0\d{2}-\d{8}|0\d{3}-\d{7}

这个表达式能匹配两种连字号分隔的电话号码:一种是三位区号,8位本地号码如010-12345678,一种是4位区号,7位本地号0376-2233445

对于上个例子,更健壮的表示如下:

\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}

 7、分组

如果想要重复多个字符又该怎么办?

可以用小括号来指定子表达式(也叫做分组),然后就可以指定子表达式的重复次数。

(\d{1-3}.){3}\d{1-3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析:

\d{1,3}匹配1到3位的数字

(\d{1-3}.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复三次

最后再加上一个一到三位的数字(\d{1,3})

IP地址中每个数字都不能大于255

正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类的描述一个正确的IP地址:

(25[0-5]|2[0-4]\d|1\d{1,2}|\d.){3}25[0-5]|24\d|1\d{1,2}|\d

8、反义

常用的反义代码
  代码/语法     说明
\W 匹配任意不是字母、数字、下划线、汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

 

9、后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本可以在表达式或者其他程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

*分组0对应整个正则表达式
*组号分配过程是要从左向右扫描两遍:第一个遍只给未命名组分配,第二遍只给命名组分配——因此所有命名组的组号都大于未命名的组号
*可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。

\b(\w+)\b\s+\1\b,可以用来匹配重复的单词,像go ,go或者kitty kitty

这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容,也就是前面匹配的那个单词(\1)

也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:

(?<word>\w+)或者把尖括号换成'也行:(?'Word'\w+),这样就把\w+的组名指定为Word。

要反向引用这个分组捕获的内容,使用\k<Word>,所以上一个例子也可以写成:

\b(?<Word>\w+)\b\s+<Word>\b

常用分组语法
分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 用于提供注释让人阅读

10、贪婪与惰性

当正则表达式中包含能接受重复的限定符,通常的行为是匹配尽可能多的字符。以这个表达式为例:a.*b,它将匹配最长的以a开始,以b结束的字符串。如果用来搜索aabab的话,它会匹配整个字符串,称为贪婪匹配。

惰性匹配是匹配尽可能少的字符。.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。

a.*?b匹配最短的,以a开始,以b结束的字符串。如果应用于aabab的话,会匹配aab和ab

懒惰限定符
代码/语法 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

11、Python之re

re有几个重要的函数:

*match():匹配字符串开始位置

*search():扫描字符串,找到第一个位置

*findall():找到全部匹配,以列表返回

*finditer():找到全部匹配,以迭代器返回

>>> import re
>>>
>>> s="12abc345ab"
>>>
>>> m = re.match(r"\d+",s)
>>>
>>> m.group(),m.span()
('', (0, 2))
>>>
>>> m = re.match(r"\d{3,}",s) #从字符串开始位置进行匹配
>>> m is None
True
>>>
>>> m = re.search(r"\d{3,}",s)
>>> m.group(),m.span()
('', (5, 8))
>>>
>>> m = re.search(r"\d+",s)
>>> m.group(),m.span()
('', (0, 2))
>>> m = re.findall(r"[a-z]{2,}",s)
>>> m
['abc', 'ab']
>>>
>>> for m in re.finditer(r"\d+",s):
... print m.group(),m.span()
...
12 (0, 2)
345 (5, 8)

findall返回列表或者空列表,finditer和match、search一样返回MatchObject对象。

12、MatchObject对象

match、search、finditer返回的对象——MatchObject

*group():返回匹配的完整字符串

*start():匹配的开始位置

*end():匹配的结束位置

*spance():包含起始、结束位置的元组

*groups():返回分组信息

*groupdict():返回命名分组信息

>> m = re.match(r"(\d+)\.(\d+)","24.136")
>>> m.groups()
('24', '136')

  >>> s
  '12ab345abc'

>>> m = re.match(r"\d+(?P<letter>[ab]+)",s)  
>>> m
<_sre.SRE_Match object at 0x7fb848229030>
>>> m.groupdict()
{'letter': 'ab'}
#可以根据letter取到相关的SQL
>>> m = re.match(r"(?P<letter>[ab]+)",s)
>>> m is None
True
#为什么这里是None,是match默认是从开始的位置进行匹配,可以设置起始位置
match:
If zero or more characters at the beginning of string match this regular expression, return a corresponding MatchObject instance. Return None if the string does not match the pattern; note that this is different from a zero-length match.
>>> pattern = re.compile("o")
>>> pattern.match("dog")
>>> pattern.match("dog",1) #重新设置起始位置
<_sre.SRE_Match object at 0x7fb848216718>