四、正则表达式

    字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。
    正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
    下面这张图展示了使用正则表达式匹配的流程
 

1、Python支持的正则表达式元字符和语法

语法 说明 表达式实例 完整匹配的字符串
字符
一般字符 匹配自己 abc abc
. 匹配任意字符“\n”除外
DOTALL模式中(re.DOTALL)也能匹配换行符
a.b abc或abc或a1c等
[...] 字符集[abc]表示a或b或c,也可以-表示一个范围如[a-d]表示a或b或c或d a[bc]c abc或adc
[^...] 非字符集,也就是非[]里的之外的字符 a[^bc]c adc或aec等
预定义字符集(也可以系在字符集[...]中)
\d 数字:[0-9] a\dc a1c等
\D 非数字:[^0-9]或[^\d] a\Dc abc等
\s 空白字符:[<空格>\t\n\f\v] a\sc a b等
\S 非空白字符:[^s] a\Sc abc等
\w 字母数字(单词字符)[a-zA-Z0-9] a\wc abc或a1c等
\W 非字母数字(非单词字符)[^\w] a\Wc a.c或a_c等
数量词(用在字符或(...)分组之后)
* 匹配0个或多个前面的表达式。(注意包括0次) abc* ab或abcc等
+ 匹配1个或多个前面的表达式。 abc+ abc或abcc等
? 匹配0个或1个前面的表达式。(注意包括0次) abc? ab或abc
{m} 匹配m个前面表达式(非贪婪) abc{2} abcc
{m,} 匹配至少m个前面表达式(m至无限次) abc{2,} abcc或abccc等
{m,n} 匹配m至n个前面的表达式 abc{1,2} abc或abcc
边界匹配(不消耗待匹配字符中的字符)
^ 匹配字符串开头,在多行模式中匹配每一行的开头 ^abc abc或abcd等
$ 匹配字符串结尾,在多行模式中匹配每一行的结尾 abc$ abc或123abc等
\A 仅匹配字符串开头 \Aabc abc或abcd等
\Z 仅匹配字符串结尾 abc\Z abc或123abc等
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。    
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。    
逻辑、分组
| 或左右表达式任意一个(短路)如果|没有在()中表示整个正则表达式(注意有括号和没括号的区别) abc|def
ab(c|d)ef
abc或def
abcef或abdef
(...) 分组,可以用来引用,也可以括号内的被当做一组进行数量匹配后接数量词 (abc){2}a abcabca
(?P<name>...) 分组别名,给分组起个名字,方便后面调用    
\<number> 引用编号为<number>的分组匹配到的字符串(注意是配到的字符串不是分组表达式本身) (\d)abc\1 1ab1或5ab5等
(?=name) 引用别名为name的分组匹配到的字符串(注意是配到的字符串不是分组表达式本身) (?P<id>\d)abc(?P=id) 1ab1或5ab5等
       
 

2、数量词的贪婪模式与分贪婪模式

    正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
 

3、python的re模块

Python通过re模块提供对正则表达式的支持。使用re的一般步骤是先将正则表达式的字符串形式编译为Pattern实例,然后使用Pattern实例处理文本并获得匹配结果(一个Match实例),最后使用Match实例获得信息,进行其他的操作。
 import re

 # 将正则表达式编译成Pattern对象
pattern = re.compile(r'hello') # 使用Pattern匹配文本,获得匹配结果,无法匹配时将返回None
match = pattern.match('hello world!') if match:
# 使用Match获得分组信息
print match.group()
执行结果
hello
当然也可以直接使用re的模块的方法时候直接传递正则表达式参数来完成
 macth = re.match('hello', 'hello world')
if match:
print match.group()
执行结果是一样的
 

4、re模块的常用方法

re.compile(strPattern[, flag])

    参数:
        strPattern:正则表达式
        flag:匹配模式,可选值有
            re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
            M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
            S(DOTALL): 点任意匹配模式,改变'.'的行为
            L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
            U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
            X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。
    返回值:Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找
    以下的方法既可以是Pattern对象的实例方法也可以是re模块的方法,语法稍有不同

match(string[, pos[, endpos]]) | re.match(pattern, string[, flags])

    这个方法将从string的pos下标处起尝试匹配pattern;如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。
    pos和endpos的默认值分别为0和len(string);re.match()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
    注意:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'。 
    参数:
    string:要匹配的字符串
    pos:匹配的开始下标
    endpos:匹配的结束下标
    pattern:正则表达式
    flags:匹配模式
    返回值:如果匹配成功返回match对象,否则返回None

search(string[, pos[, endpos]]) | re.search(pattern, string[, flags])

    这个方法用于查找字符串中可以匹配成功的子串。从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象;若无法匹配,则将pos加1后重新尝试匹配;直到pos=endpos时仍无法匹配则返回None。
pos和endpos的默认值分别为0和len(string));re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。 
    参数:同match
    返回值:同match
 
    我们通过一个实例来看一下两个方法的区别
>>> import re
>>> s = 'hello world'
>>> print(re.match('ello', s))
None
>>> print(re.search('ello',s ))
<_sre.SRE_Match object; span=(1, 5), match='ello'>
说明:可以看到macth只匹配开头,开头不匹配,就不算匹配到,search则可以从中间,只要能有匹配到就算匹配
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
搜索string,以列表形式返回全部能匹配的子串。有点像search的扩展,把所有匹配的子串放到一个列表
参数:同match
返回值:所有匹配的子串,没有匹配则返回空列表
>>> import re
>>> s = 'one1two2three3four4'
>>> re.findall('\d+', s)
['', '', '', '']

split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):

    按照匹配字子串将字符串进行分割,返回分割收的列表
    参数:
     string:要分割的字符串
     pattern:正则表达式
    maxsplit:最大分割次数
    返回值:分割后的列表
    实例
>>> import re
>>> s = 'one1two2three3four4'
>>> re.split('\d+', s)
['one', 'two', 'three', 'four', '']

sub(repl, string[, count]) | re.sub(pattern, repl, string[, count])

    使用repl替换string中匹配的每一子串
    参数:
    repl:替换的字符串或方法,这里需要说一下这个方法,方法接收macth对象,方法的返回值作为替换的字符串,换句话就是经过处理的字符串。
    string:要进行替换的字符串
    pattern:正则表达式
    count:替换的次数
    实例:对于repl是个方法的情况,正好这次作业用到,用来替换多个则很难过福号的情况。假设我们有一个四则运算表达式 '--(1.1+1+1-(-1)-(1+1+(1+1+2.2)))+-----111+--++--3-+++++++---+---1+4+4/2+(1+3)*4.1+(2-1.1)*2/2*3',遵循奇数个负号等于正否则为负的原则进行替换,我们可以这样
 if __name__ == '__main__':
import re
s = '--(1.1+1+1-(-1)-(1+1+(1+1+2.2)))+-----111+--++--3-+++++++---+---1+4+4/2+(1+3)*4.1+(2-1.1)*2/2*3'
def replace_sign(expression):
'''
替换多个连续+-符号的问题,例如+-----,遵循奇数个负号等于正否则为负的原则进行替换
:param expression: 表达式,包括有括号的情况
:return: 返回经过处理的表达式
'''
def re_sign(m):
if m:
if m.group().count('-')%2 == 1:
return '-'
else:
return '+'
else:
return ''
expression = re.sub('[\+\-]{2,}', re_sign, expression)
return expression s = replace_sign(s)
print(s)

  执行结果

24 +(1.1+1+1-(-1)-(1+1+(1+1+2.2)))-111+3-1+4+4/2+(1+3)*4.1+(2-1.1)*2/2*3

我的Python成长之路---第四天---Python基础(16)---2016年1月23日(寒风刺骨)的更多相关文章

  1. 我的Python成长之路---第四天---Python基础(15)---2016年1月23日(寒风刺骨)

    二.装饰器     所谓装饰器decorator仅仅是一种语法糖, 可作用的对象可以是函数也可以是类, 装饰器本身是一个函数, 其主要工作方式就是将被装饰的类或者函数当作参数传递给装饰器函数.本质上, ...

  2. 我的Python成长之路---第四天---Python基础(14)---2016年1月23日(寒风刺骨)

    一.生成器和迭代器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退. ...

  3. 我的Python成长之路---第三天---Python基础(13)---2016年1月16日(雾霾)

    五.Python的常用的内置函数 Python为我们准备了大量的内置函数,如下图所示 这里我们只讨论红框内的内置函数 abs(x) 返回一个数的绝对值(模),参数可以是真说或浮点数 >>& ...

  4. python成长之路——第四天

    内置函数: callable:查看对象是否能被调用(对象是函数的话能被调用) #callable def f1(): pass f2="a" print(callable(f1)) ...

  5. 我的Python成长之路---第七天---Python基础(21)---2016年2月27日(晴)

    四.面向对象进阶 1.类方法 普通的方法通过对象调用,至少有一个self参数(调用的时候系统自动传递,不需要手工传递),而类方法由类直接调用,至少有一个cls参数,执行时,自动将调用该方法的类赋值个c ...

  6. 我的Python成长之路---第三天---Python基础(12)---2016年1月16日(雾霾)

    四.函数 日常生活中,要完成一件复杂的功能,我们总是习惯把“大功能”分解为多个“小功能”以实现.在编程的世界里,“功能”可称呼为“函数”,因此“函数”其实就是一段实现了某种功能的代码,并且可以供其它代 ...

  7. 我的Python成长之路---第三天---Python基础(11)---2016年1月16日(雾霾)

    三.深浅拷贝 在Python中将一个变量的值传递给另外一个变量通常有三种:赋值.浅拷贝以及深拷贝 讨论深浅拷贝之前我们把Python的数据类型分为基本数据类型包括数字.字符串.布尔以及None等,还有 ...

  8. 我的Python成长之路---第三天---Python基础(10)---2016年1月16日(雾霾)

    二.collections collections是对Python现有的数据类型的补充,在使用collections中的对象要先导入import collections模块 1.Counter——计数 ...

  9. Python高手之路【四】python函数装饰器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

随机推荐

  1. HDU 2138 How many prime numbers

    米勒罗宾素数测试: /* if n < 1,373,653, it is enough to test a = 2 and 3. if n < 9,080,191, it is enoug ...

  2. USACO 2001 OPEN

    第1题 绿组. 奶牛接力赛[relay] 题目描述 农夫约翰已经为一次赛跑选出了K(2≤K≤40)头牛组成了一支接力队.赛跑在农夫约翰所拥有的农场上进行,农场的编号为1到Ⅳf4≤Ⅳ< 800), ...

  3. HDOJ Sudoku Killer(dfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1426 思路分析:该问题为数独问题,明显解是唯一的,所有采用dfs搜索效果更好: 在搜索时,可以通过3个 ...

  4. iOS --- [持续更新中] iOS移动开发中的优质资源

    在我们做iOS APP的开发过程中, 须要非常多设计, 产品, 技术, 运营等方面的技巧和资源. 现将其整理汇总, 本文会一直持续更新. 敬请关注. 设计 Dribbble Dribbble是一个面向 ...

  5. MyReport报表引擎2.6.5.0新功能

    新的文本渲染引擎,打印旋转时保持文本高精度矢量输出,打印更清晰.  watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva29uZ195ZWU=/font/5a6 ...

  6. SVNserver的本地搭建和使用

    Subversion是优秀的版本号控制工具,其具体的的长处和具体介绍,这里就不再多说. 首先来下载和搭建SVNserver. 如今Subversion已经迁移到apache站点上了,下载地址: htt ...

  7. Sublime 操作技巧

    吐槽一下:刚下载的subime不是等宽字体,空格.表达.字母i什么的都很窄,看着不方便: 根据网上说的换成等宽字体,试了好多种字体,字体变了.但宽度没变. 然后有装了soda,和相应的color-th ...

  8. 解决:Visual Assist X 不支持HTML、Javascript等提示

    Visual Assist X 安装后,不能进行javascript hmtl提示,只有回到老版本才行.这个问题折腾了老久,才给解决了. 记录下来,以便于网友和自己使用. 问题原因: Visual A ...

  9. STL之map和multimap(关联容器)

    map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响.自动建立Key - value的对应,对于迭代器来说,可以修改实值,而不能修改key. ...

  10. jquery选择器控制Html元素

    1.JQuery中有addClass,removeClass,toggleClass addClass(class):为每个匹配的元素添加指定的类名 removeClass(class):从所有匹配的 ...