正则表达式又称规则表达式(Regular Expression),通过一定的规则,用来对文本(字符串)内容进行检索、替换。
要搜索的模式和字符串都可以是Unicode字符串(str)以及8位ASCII字符串(字节)。但是,Unicode字符串和ASCII符串不能混合使用。也就是说,无法将Unicode字符串与字节模式匹配,反之亦然;同样,当要求替换时,替换字符串必须与模式和搜索字符串的类型相同。
这些建立的规则在使用时又叫模式字符串。一个正则表达式模式中的字母和数字匹配同样的字符串。
- 字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会有不同的含义。
- 标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
- 反斜杠本身需要反斜杠转义。 由于正则表达式通常都包含反斜杠,所以最好使用原始字符串来表示它们。模式元素(如r'\t',等价于r'\\t')匹配相应的特殊字符。
- 正则表达式可以连接起来形成新的正则表达式。如果A和B都是正则表达式,那么AB也是一个正则表达式。通常如果一个字符串p匹配A而另外一个字符串q匹配B,那么,字符串pq匹配字符AB。除非A或B包含包含低优先级操作,A和B之间的边界条件,或者有编号的组参考。因此,复杂的表达式可以很容易地从简单的基本表达式构建,就像这里描述的那样。
- 正则表达式可以包含特殊字符和普通字符。大多数普通字符,如'A'、'a'或'0'是最简单的正则表达式。它们指数匹配自己。可以连接普通字符,因此最后匹配字符串'last'。
特殊字符,一些字符'|'或者'()'是特殊的,特殊字符或者代表普通字符类,或者影响它们周围正则表达式的解释方式。特殊符号和字符如下所示(主要包括普通字符、11个元字符、特殊字符):
符号 | 使用说明 | 示例 |
^ | 匹配字符串的起始部分 | ^Cat |
$ | 匹配字符串的末尾部分 | Cat$ |
. | 匹配任意字符,除了换行符(/n) | Cat.cool |
[···] | 用来匹配字符集中的任意单个字符 | [abc] |
[^···] | 匹配不在[]中的字符 | [^abc] |
* | 匹配0个或者多个的表达式 | [abc]* |
+ | 匹配1个或者多个的表达式 | [abc]+ |
? | 匹配0个或者1个由前面的正则表达式定义的片段 | Cat? |
{n} | 精确匹配n次前面出现的表达式 | [0-9] {2} |
{n,} | 匹配n次前面出现的表达式 | oo {2,} |
{n,m} | 匹配n到m次由前面的正则表达式定义的片段,贪婪方式 | [0-9] {2,4} |
a | b | 匹配a或者b | Cat | abc |
(···) | 匹配括号内的表达式,然后另存匹配的值 | (abc ?) |
(?-imx) | 正则表达式 关闭i、m或x可选标志,只影响括号中的匹配 | (?-imx) |
(?···) | 类似(...),但是不另存匹配的值 | [?:abc] |
(?imx:···) | 在括号中使用i、m或x可选标志 | (?imx:abc) |
(?-imx:···) | 在括号中不使用i、m或x可选标志 | (?-imx:abc) |
(?#.···) | 注释,所有内容都被忽略 | (?#OK) |
(?=···) | 前向肯定界定符 | (?=.com) |
(?!···) | 前向否定界定符 | (?!.cn) |
(?>···) | 匹配的独立模式,省去回溯 | (?>20) |
\w | 匹配任意字母、数字及下划线 | (\w) |
\W | 匹配非字母、数字及下划线 | (\W) |
\s | 匹配任意空白字符,等价于[\t\n\r\f] | (\s) |
\S | 匹配任意非空字符 | (\S) |
\d | 匹配任意数字 | (\d) |
\D | 匹配任意非数字 | (\D) |
\A | 匹配字符串开始 | \Agood |
\Z | 匹配字符串结束,如果存在换行,只匹配到换行前的结束字符串 | good\Z |
\z | 匹配字符串结束 | good\z |
\G | 匹配最后匹配完成的位置 | Good\G |
\b | 匹配一个单词边界,也就是指单词和空格间的位置 | Good \b and \b |
\B | 匹配非单词边界 | T\B |
\n,\t | 匹配一个换行符,匹配一个制表符 | Bird\n\t |
\1...\9 | 匹配第n个分组的内容 | \1abc |
代码示例:
import re
m=re.search('(?<=abc)def','abcdef')
print(m.group(0))
m=re.search('(?<=-)\w+','spam-egg') #匹配从-开始的任意数字、字母及下划线
print(m.group(0))
输出结果:
def
egg
###########################################################################################
注意:Python的字符串本身也用'\'转义,所以要特别注意,一般我们都建议使用Python的r前缀,就不用考虑转义的问题了
1,行的起始
例子:匹配‘cat’ 开头
patt=re.compile(r'^cat') # re.compile 返回一个正则表达式对象
表示匹配以c作为一行的第一个字符,后面跟着a,后面跟着t
所以'vocative'就不会被匹配到,原因是因为cat在字符的里面
2,行的结尾
import re sentence='''Hi Jack:\n Python is a beautiful language\n BR'''
patt=re.compile(r'(BR|Bestregards)$')
m=re.search(patt,sentence)
if len(m)>=0 :
print 'match'
else:
print 'not match'
>> match
要查找sentence中是否以“BR或Bestregards” 结尾
3 ,单词的边界
正则里面有2个特殊字符\b and \B来匹配单词的边界 :
-
\b 匹配的模式是一个单词的边界(不论这个单词的前面是有字符还是没有字符)
-
\B 匹配出现在一个单词中间的模式
-
例如:
the #匹配包含有'the'的字符串
\bthe #匹配任何以'the'开始的字符串
\bthe\b #仅仅匹配单词'the'
\Bthe #匹配任意包含'the'但不以'the'开头的单词
4,字符组
比如我们需要匹配'grey'或者'gray'的时候,怎么办,可以用正则的[]来表示,gr[ea]y,表示先找到g,然后找到r,然后找到e或者a,最后是一个y
patt=re.compile(r'gr[ea]y')#意思就是grey 或者gray都是可以匹配上的
5,多选结构
我们可以用'|'来匹配任意子表达式,'|'是一个非常简便的元字符,它的意思是"或",通过它我们能把不同的子表达式组合成一个总的表达式,比如'am'|'pm'就是能够同时匹配其中任意一个的正则表达式,回头再看上面的例子'gr[ea]y',其实能写成'grey|gray',或者'gr(e|a)y'
6、可选项元素
'?' 表示可选项,问号跟在什么后面就表示什么是可选的
例如:6月4日,可能写成'June'也可以写成'Jun',而且日期也有可能写作'fourth'或者'4th'或者4,这个时候就可以写成June?(fourth|4(th)?),代表了e是可选的,th是可选的,可有可无都表示4号
7,重复出现
+,表示紧邻元素重复出现一次或者多次,至少出现一次,否则返回失败;
*,表示紧邻元素重复出现0次或者多次,允许出现0次;
例如:
- a*表示0个或者多个a,所以为0的时候,就是空字符
- a+表示1个或者多个a,所以a至少要有1次
8,匹配重复的次数
次数用{}里面的数字来表示
例如:patt=re.compile(r'([1-9]{3})') 就表示匹配1-9之间的数字,且这个数字只能出现3次,str='123str' ,就可以匹配上,而str1='2str1'就不能匹配,如果想匹配上要这么写patt1=re.compile(r'([1-9]{1-3})'),1-9数字出现1次或2次或3次
9、排除型字符组
-
当^在字符组的外面的时候"表示一个行的开头"
-
当^在字符组的内部(而且是必须紧接着字符组的第一个方括号之后),它就是一个元字符,表示排除型
- 例如:找出字母g后面的字母不是u
-
import re words=['gold',' Google','Sogu','Guess'] patt=re.compile(r'.*g[^u]') #‘.’匹配任意一个字符,'*'匹配0个或多个字符,g后面不是u for w in words: m=re.match(patt,w) if m: print w >> gold Google
实战小例子
1,设计一个正则来过滤一个字符串序列中的10到59
import re
patt=r'[1-5][0-9]'
lis=[10,20,30,40,2,3,59,60,'aa','3aaa']
match=re.findall(patt,str(lis))
if match:
print(match)
结果:
['10', '20', '30', '40', '59']
2,过滤字符串中的只含2个字符的字母,并且第一个字母是大写A或B或C
patt=r'[A-C][A-Z a-z]'
3,过滤一个字符串中的含3个字母的独立字符
例如:比如这样的一个字符串'xy,1,2,?,123@sohu,Ab,w1,Cz,xyh,abc',只想过滤出来xyh,abc 这样的
patt=r'/b[a-z A-Z]{3}/b' #/b 单词的边界
4、过滤一个字符串中的含3个字母的字符,并且最后一个字母是z
patt=r'/b[a-z A-Z][a-z A-Z][Z]/b'
5,过滤正确的24小时时间制
import re
time='10:00,99:90,8:00,19:19:14:00pm,5:xm,6,00,8:0923:23pm,29:19pm,23:59'
patt = r'\b([01]?[0-9]|2[0-4])(:)([0-5][0-9])'
match = re.findall(patt,time)
if match:
print([''.join(x)for x in match])
执行结果:
['10:00', '8:00', '19:19', '14:00', '8:09', '23:59']
****************************************************************************************************************
re模块中常用功能函数
1、compile()
编译正则表达式模式,返回一个对象的模式。(可以把哪些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率)
格式:
re.compile(pattern,flags=0)
标志flags:
- re.S(DOTALL) 使.匹配包括行在内的所有字符
- re.I(IGNORECASE) 使匹配对大小写不敏感
- re.L(LOCALE) 使用本地化识别 (locale-aware)匹配,法语等
- re.M(MULTILINE) 多行匹配,影响^和$
- re.X(VERBOSE) 该标志通过给与更灵活的格式以便将正则表达式写得更易于理解
- re.U 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B
import re
tt ='Tina is a good girl,she is cool,clever, and so on...'
patt=re.compile(r'\w*oo\w*')
print(re.findall(patt,tt))
输出结果:
['good', 'cool']
2、match()
决定RE是否在字符串刚开始的位置匹配。
print(re.match('com','comwwwww.runconoob').group())
print(re.match('com','CoMEEEE',re.I).group())
输出结果:
com
CoM
3、search()
re.search(pattern,string,flags=0)
re.search()函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
re.search('\dcom','ddd2dcom.333ss.1com').group())
输出结果:
2com
注意:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
- group()返回被RE匹配的字符串
- start()返回匹配开始的位置
- end()返回匹配结束的位置
- span()返回一个元组包含的匹配(开始,结束)的位置
- group()返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)) #123abc456,返回整体
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)) #123
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)) #abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)) #456
###group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。###
4、findall()
re.findall()遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。
re.findall(pattern,string,flags=0)
示例:
p=re.compile(r'\d+')
print(re.findall(p,'o1m2n3b4'))
输出结果:
['1', '2', '3', '4']
tt ='Tina is a good girl,she is cool,clever, and so on...'
print(re.findall('(\w*)oo(\w)',tt))
输出结果:
[('g', 'd'), ('c', 'l')]
5、finditer()
搜索string,返回一个顺序访问每一个匹配结果的迭代器。找到RE匹配的所有子串,并把它们作为一个迭代器返回。
6、split()
按照能够匹配的子串将string分割后返回列表。
可以使用re.split来分割,如:re.split(r'\s+',text),将字符串按照空格分割成一个单词列表。
print(re.split(r'\d+','ddd1eeeee23ddddd45mmmm6'))
输出结果:
['ddd', 'eeeee', 'ddddd', 'mmmm', '']
7、sub()
使用re替换string中每一个匹配的子串后返回替换后的字符串
格式:re.sub(pattern,repl,string,count)
tt ='Tina is a good girl,she is cool,clever, and so on...'
print(re.sub('\s+','-',tt)) #将空格替换为-
输出结果:
Tina-is-a-good-girl,she-is-cool,clever,-and-so-on...
8、subn()
返回替换的次数。
格式:re.subn(pattern,repl,string,count=0,flags=0)
tt ='Tina is a good girl,she is cool,clever, and so on...'
print(re.subn('\s+','-',tt)) #subn()得到替换的次数
输出结果:
('Tina-is-a-good-girl,she-is-cool,clever,-and-so-on...', 9)
注意点
1、re.match与re.search、re.findall()的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
a=re.search('[\d]',"abc33").group()
print(a)
p=re.match('[\d]',"abc33")
print(p)
b=re.findall('[\d]',"abc33")
print(b)
执行结果:
3
None
['3', '3']
2、贪婪匹配与非贪婪匹配
*? +? ?? {m,n}?前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?使其编程惰性匹配。(如果前后都有限定条件,则不存在贪婪模式)
a=re.findall(r'a(\d+?)','a23456dddd')
print(a)
b=re.findall(r'a(\d+)','a23456drr456dddd')
print(b)
输出结果:
['2']
['23456']