python 正则表达式基础

正则表达式对于初学者来说,要用好这个功能还是有点难度,也看了好久书加练习才掌握一些基础。对学到的一些东西还是写下来比较好一些,免得过几天又忘了。

常用符号:. * ? ()

常用方法: findall search sub

常用技巧

1 Python 正则式的基本用法

  Python 通过标准库re模块支持正则表达式。

>>> import re
>>> string = "XXXIXXXLoveXXX"
>>> re.findall('XXX(.*?)XXX', string)
['I']
>>> 
 

在python术语中,有两种主要方法完成模式匹配:serarching 和matching.

搜索:在字符串中任意部分中搜索匹配模式。

匹配:判断一个字符串是否能从起始位置全部或部分匹配某个模式。

 

常用正则符号字符如下图:

a. 基本规则

'.'   匹配所有字符

匹配除换行符 '\n' 外的所有字符。如果使用了 'S' 选项,匹配包括 '\n' 的所有字符。要明确的匹配一个'.',必须使用’\‘对它进行转义。

>>> s = """XXX
IXXX"""
>>> re.findall('.+', s)
['XXX', 'IXXX']
>>> re.findall('.+', s, re.S)
['XXX\nIXXX']
>>> 

b.  对基本规则作限定(闭包操作符)

'*'   0 或多次匹配。常用.*(贪心算法)

>>> x = "abc2323sf23"
>>> re.findall('c.*s', x)
['c2323s']
>>> 

'+'   1 次或多次匹配

>>> x = "abc2323sf23"
>>> re.findall('c\d+s', x)
['c2323s']
>>> 

'?'  0 或 1 次匹配。常用.*?(非谈心算法)

>>> x = "abc2323sf23"
>>> re.findall('c\d?', x)
['c2']
>>> re.findall('c\d+?', x)
['c2']
>>> re.findall('c.*?', x)
['c']

‘{m}'精确匹配 m 次

‘{m,n}'匹配最少 m 次,最多 n 次

2. ()创建组

一对()和正则表达式一起使用可达到:

  a. 对正则进行分组

  b. 匹配子组

>>> s= 'XXXIXXXLOVEXXXYOU'
>>> re.findall('XXX(.*)XXX(.*)XXX(.*)', s)
[('I', 'LOVE', 'YOU')]
>>>

 可以看到 findall 函数只返回了包含在 ’()’ 中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。

3. 常用函数

findall(pattern, string[,flags])

在目标字符串中查找符合规则的字符串。

第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项。

返回结果结果是一个列表 中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。

常用规则选项

I       IGNORECASE 忽略大小写区别。

L   LOCAL   字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符/w ,在英文环境下,它代表[a-zA-Z0-9] ,即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配 "é" 或 "ç" 。 加上这 L 选项和就可以匹配了。不过这个对于中文环境似乎没有什么用,它仍然不能匹配中文字符。

M     MULTILINE  多行匹配。在这个模式下 ’^’( 代表字符串开头 ) 和 ’$’( 代表字符串结尾 ) 将能够匹配多行的情况,成为行首和行尾标记。

当我们调用findall()方法,我们可以非常简单的得到一个所有匹配模式的 列表,而不是得到对象。

>>> string = 'bird cat bird, cat dog'
>>> s = re.findall(r'cat', string)
>>> s
['cat', 'cat']
>>> 

 

match 与 search

match( pattern, string, flags = 0)

search( pattern, string, flags = 0)

match函数尝试从字符串的开头开始对模式进行匹配,如果匹配成功,就返回一个匹配对象,如果失败返回空,匹配对象的group()方法可以用来显示那个成功的匹配。

search函数工作方式和match一样,这两个函数唯一的区别是: match 从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而 search 会跳过开头,继续向后寻找是否有匹配的字符串。

常见例子:

 对字符串'bird cat bird'调用mathch()方法,查找模式'bird'将会匹配:

>>> re.match(r'bird', 'cat bird cat')
>>> string = 'bird cat bird'
>>> s = re.match(r'bird', string)
>>> s
<_sre.SRE_Match object at 0x0000000003104D30>
>>> s.group()
'bird'
>>> s = re.match(r'cat', string)
>>> s
>>> 

 但是,如果我们对同一个字符串调用math()方法,查找模式'cat',则不会找到匹配。

而search()结果则不一样,search()方法会在它查找到一个匹配项之后停止继续查找,并返回其首次出现的位置。

>>> string = 'bird cat bird'
>>> s = re.search(r'cat', string)
>>> s
<_sre.SRE_Match object at 0x0000000003104D30>
>>> s.group()
'cat'
>>> 

 

分组示例:

即:上面提到的'()'号,对整个正则表达式的特定子串进行定位的能力。我们可以定义一个分组做为整个正则表达式的一部分,然后单独的对这部分对应匹配到的内容定位。

>>> string = "name: Tom, phone: 12344"
>>> s = re.findall(r'(.*): (.*), phone: (\d+)',string)
>>> s
[('name', 'Tom', '12344')]
>>> s = re.search(r'(.*): (.*), phone: (\d+)',string)
>>> s
<_sre.SRE_Match object at 0x0000000002F54AE0>
>>> s.group(1)
'name'
>>> s.group(2)
'Tom'
>>> s.group(3)
'12344'
>>> 

 

 通过用圆括号来(字符‘(’和‘)’)包围正则表达式的特定部分,可以对内容进行分组然后对这些子组做单独处理。

总结:

  1. 数量词的贪婪和非贪婪

  贪婪:总是尽可能匹配可能多字符。 

>>> import re
>>> a = 'ab*'
>>> re.findall(a, 'abbbc')
['abbb']
>>> 

  非贪婪:总是尝试尽可能少的字符。(常用)

>>> re.findall('ab*?', 'abbbc')
['a']
>>> 

  2. 反斜杠问题

  与大多数编程语言相同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\\\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

  Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\\”表示。同样,匹配一个数字的”\\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

  3.Re 模块

  re模块主要方法

  re.compile(string[,flag]) #返回pattern对象

  re.match(pattern, string[, flags])

  re.search(pattern, string[,flags])

  re.finadll(pattern, string[,flags])

  pattern: pattern可以理解为一个匹配模式,需要利用re.compile方法获得。

  例如:pattern = re.complie('aa*'), 通过compile方法编译生成一个pattern对象,然后我们利用这个对象来进行进一步的匹配。在刚才所说的另外几个方法例如 re.match 里我们就需要用到这个pattern了, 参数flag是匹配模式,取值可以使用按位或运算符’|’表示同时生效,比如re.I | re.M。

  re.M(全拼:MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
  re.S(全拼:DOTALL): 点任意匹配模式,改变'.'的行为

  re.L(全拼:LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定

  re.U(全拼:UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性

  re.X(全拼:VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。

  a. re.match(pattern, string[, flags]

  这个方法将会从string(我们要匹配的字符串)的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符,立即返回None,如果匹配未结束已经到达string的末尾,也会返回None。两个结果均表示匹配失败,否则匹配pattern成功,同时匹配终止,不再对string向后匹配。

>>> pattern = re.compile(r'hello')
>>> result1 = re.match(pattern,'hello')
>>> result1
<_sre.SRE_Match object at 0x0000000002D9E780>
>>> result1.group()
'hello'
>>> result1 = re.match(pattern,'nihao hello, ac')
>>> result1.group()

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    result1.group()
AttributeError: 'NoneType' object has no attribute 'group'
>>> 

  Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息.(下面部分copy百度现成)

    1.string: 匹配时使用的文本。
    2.re: 匹配时使用的Pattern对象。
    3.pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
    4.endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
    5.lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
    6.lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。

    方法:
    1.group([group1, …]):
    获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
    2.groups([default]):
    以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
    3.groupdict([default]):
    返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
    4.start([group]):
    返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
    5.end([group]):
    返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
    6.span([group]):
    返回(start(group), end(group))。
    7.expand(template):
    将匹配到的分组代入template中然后返回。template中可以使用\id或\g、\g引用分组,但不能使用编号0。\id与\g是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符’0’,只能使用\g0。

  b. re.search(pattern, string[, flags])

    search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性。

>>> pattern = re.compile(r'Hello')
>>> match = re.search(pattern, 'WW,Hello,World')
>>> match
<_sre.SRE_Match object at 0x0000000002D9E780>
>>> match.group()
'Hello'
>>> match = re.search(pattern, 'WW,Helllo,World')
>>> match
>>> 

  c. re.findall(pattern, string[,flags])

  搜索string,以列表形式返回全部能匹配的子串.

>>> pattern = re.compile(r'\d+')
>>> re.findall(pattern, 'testx232xsdf3dsf3')
['232', '3', '3']
>>> 

  

  

 

  

 

posted @ 2016-04-09 13:18  小阿Q的博客  阅读(333)  评论(0编辑  收藏  举报