re模块包含正则表达式的支持,这个功能很有用,所以单独拿出来
正则表达式的学习中,每次只需根据自己的需要一次只学一点,不必一次性全部掌握
除了标准文档外,http://amk.ca/python/howto/regex/ 也是这方面的有用资源

正则表达式

  • 通配符
    小数点(.)表示一个任意字符(除了换行符)
  • 重复
    在字符后接加号(+)表示这个字符可以重复多次,如ht+p
  • 特殊字符转义
    反斜线(\)
  • 字符集
    方括号([])把可以匹配的字符包含起来成为字符集,这样就可以匹配到字符集内的任意字符一个,如[abc]
    还可以用横线(-)可以指定范围,如[a-zA-Z0-9]
    脱字符(^)可以创建一个反转字符集,如[^abc]表示除了'a','b','c'的任意字符一个
    在字符集中的字符一般不需要转义(除了^、-、]等字符集里的特殊字符),不过转义倒也是合法的
  • 选择符和子模式
    管道符号(|)表示“或”,如python|perl
    圆括号(())表示括号内为子模式,即是在限制括号内符号的作用范围,如p(ython|erl)
  • 可选项和重复子模式
    子模式后接问号(?)表示子模式是可选的,可有可无的,如(http://)?(www\.)?python\.org
    子模式后接星号(*)表示子模式可以重复零到无穷多次,如(pattern)*
    子模式后接加号(+)表示子模式可以重复一到无穷多次,如(pattern)+
    子模式后接花括号({m, n})表示子模式可以重复m~n次,如(pattern){m, n},也可以是(pattern){n}直接指定为n次
    这些符号不止可以用在子模式中,还可以用在普通的单个字符或者通配符

更多运算符参考http://python.org/doc/lib/re-syntax

re模块内容

  • compile(pattern[, flags]):根据包含正则表达式的字符串创建模式对象(形成规则,可以多次调用匹配)
    其实在调用search和match时也会在内容创建模式对象的
    模式对象本身具有search和match函数,用法与re模块的同名函数一致
    flags参数用于改变解释正则表达式的方法
  • search(pattern, string[, flags]):在字符串中寻找指定模式的子字符串
    若查找到第一个匹配项,即返回MatchObject(值为True)
    若查找不到,即返回None(值为False)
  • match(pattern, string[, flags]):在字符串的开始处匹配模式
    只会匹配开始部分,不会匹配整个字符串
    但可以在模式的末尾加入美元符号($),使这个模式“顺延”整个字符串
    如果匹配到了,返回MatchObject对象,否则返回None
  • split(pattern, string[, maxsplit=0]):根据模式的匹配项来分割字符串
    如果模式包含子模式,那么子模式也是匹配的一部分,但是字符串分割后会把子模式内的组合作为分割后的间隔字符串
  • findall(pattern, string):列出字符串中模式的所有匹配项
  • sub(pat, repl, string[, count=0]):将字符串中所有pat的匹配项用repl替换
    repl参数中可以以反斜杠加数字的形式表示组,如\1表示组1
    repl还可以是一个作为替换规则的函数
  • escape(string):将字符串中所有特殊正则表达式字符加上反斜杠转义

在re模块的函数中可以使用VERBOSE标志,即加入一个re.VERBOSE作为参数
它允许在模式中添加空白(空格、tab、换行符等),当需要使用空白符时再用反斜杠进行转义,也可以使用#注释

import re

In [6]:
re.split('o(xx)', 'foobar|foxxbar|foxxoxxbar')
Out[6]:
['foobar|f', 'xx', 'bar|f', 'xx', '', 'xx', 'bar']
In [3]:
re.findall('[a-zA-Z]+', '"Hm...Err -- are you sure?" he said. sounding insecure')
Out[3]:
['Hm', 'Err', 'are', 'you', 'sure', 'he', 'said', 'sounding', 'insecure']
In [5]:
re.escape("www.python.com")
Out[5]:
'www\\.python\\.com'

匹配对象和组

匹配模式的子字符串(子模式)称为组,组号与左端左括号数相等,整个字符串为组0
如:'There (was a (wee) (cooper)) who (lived in Fyfe)'包含以下组

  • 0 There was a wee cooper who lived in Fyfe
  • 1 was a wee cooper
  • 2 wee
  • 3 cooper
  • 4 lived in Fyfe

部分函数会返回MatchObject对象,这个对象包含匹配模式的各个组的信息,可以通过一些方法来访问

  • group([group1, ......]):获取给定的组的匹配项(若为多个组,将以元组的形式给出)
  • start([group]):返回给定组匹配项的起始位置(索引)
  • end([group]):返回给定组匹配项的结束位置(索引+1,便于分片使用)
  • span([group]):返回给定组匹配项的始末位置(以元组(start, end)地形式返回)

这些方法可以省略参数,默认为组0即整个字符串

In [8]:
m = re.match(r'www\.(.*)\..{3}', 'www.python.org')
#模式使用原始字符串,防止反斜杠被提前转义
#.*表示任意数量的任意字符
#.{3}表示三个任意字符
#这个模式匹配到的是,'www.'  任意数量的任意字符 . 三个任意字符
#组0为www.python.org
#组1为python
In [9]:
m.group(1)
Out[9]:
'python'
In [10]:
m.start(1)        #起始索引
Out[10]:
4
In [11]:
m.end(1)        #结束索引 + 1
Out[11]:
10
In [12]:
m.span(1)            #起始和结束索引
Out[12]:
(4, 10)

sub函数——作为替换的组号和函数

模拟markdown将“*somthing*”自动转换为HTML标签的“< em>somthing< /em>”

In [13]:
emphasis_pattern = re.compile(r'''
    \*            #Beginning emphasis tag -- an asterisk
    (              #Begin group for capturing phrase
    [^\*]+      #Capture anything except aster
    )              #End group 
    \*            #Ending emphasis tag
    ''', re.VERBOSE)               #对compile函数采用VERBOSE标志,对模式进行详细说明
In [14]:
re.sub(emphasis_pattern, r'<em>\1</em>', 'Hello *world*!')
#这里的第二个参数使用了“\1”,这里表示组1
#等价于emphasis_pattern.sub(r'<em>\1</em>', 'Hello *world*!')
Out[14]:
'Hello <em>world</em>!'
  • 贪婪(greedy)和非贪婪模式
    上面的模式中“[^*]+”表示任意数量的非星号字符,如果我们把它改成“.+”任意数量字符呢?
In [15]:
emphasis_pattern = r'\*(.+)\*'
In [16]:
text = '*This* is *it*!'
In [17]:
repl = r'<em>\1</em>'
In [19]:
re.sub(emphasis_pattern, repl, text)
#模式匹配了从开始星号到结束星号的所有内容,这就是贪婪模式
Out[19]:
'<em>This* is *it</em>!'
In [20]:
emphasis_pattern = r'\*(.+?)\*'
#我们在+后面加上?,即变为非贪婪模式,它仅会匹配到下一个匹配项前的最少内容
In [21]:
re.sub(emphasis_pattern, repl, text)
Out[21]:
'<em>This</em> is <em>it</em>!'
In []: