Python 正则表达式

Posted yc紫日

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 正则表达式相关的知识,希望对你有一定的参考价值。

1.正则表达式基本概念

背景

我们要匹配以xxx开头的字符串、xxx结尾的字符串等时,每一次匹配都要单独写一个函数或语句来完成,正则表达式就是将匹配的方法抽象成一个规则,然后使用这个规则来进行文本或数据的匹配。

概念

是使用单个字符串来描述匹配一系列符合某个语法规则的字符串

是对字符串操作的一种逻辑公式

应用场景

处理文本或数据

处理过程

依次拿出表达式和目标数据进行字符比较,如果每一个字符都能匹配,则匹配成功,否则,失败。

2.Python正则表达式之re模块

字符串自带的查找方法

str1.find(str2)

str1.startswith(str2)

str2.endswith(str2)

详见:python基础--02 Python内置基本类型中的1.4节

re模块使用

导入re模块

import re

生成pattern实例

pa=re.pattern(正则表达式, flag)

参数

         正则表达式

                  最好是raw字符串;

                  如果正则表达式首位带括号,则最终的match实例.groups()方法可以以元组的形式展示匹配到的字符串,如r\'(study)\',但是元组中始终只有一个元素。

         flag

                  re.A | re.ASCII

                           对\\w、\\W、\\b、\\B、\\d、\\D、\\s和\\S产生影响,编译后的模式对象在进行匹配的时候,只会匹配ASCII字符,而不是Unicode字符。

                  re.I | re.IGNORECASE

                           在匹配的时候忽略大小写

                  re.M | re.MULTILINE

                           默认,元字符^会匹配字符串的开始处,元字符$会匹配字符串的结束位置和字符串后面紧跟的换行符之前(如果存在这个换行符)。

                           如果指定了这个选项,则^将会匹配字符串的开头和每一行的开始处,紧跟在每一个换行符后面的位置。

                           类似的,$会匹配字符串的最后和每一行的最后,在接下来的换行符的前面的位置。

>>> p = re.compile(r\'(^hello$)\\s(^hello$)\\s(^hello$)\\s\')
>>> m = p.search(\'hello\\nhello\\nhello\\n\')
>>> print(m)

None

>>> p = re.compile(r\'(^hello$)\\s(^hello$)\\s(^hello$)\\s\', re.M)
>>> m = p.search(\'\\nhello\\nhello\\nhello\\n\')
>>> m.groups()

(\'hello\', \'hello\', \'hello\')

                  re.S | re.DOTALL

                           使得.元字符可以匹配任何字符,包括换行符。

                  re.X | re.VERBOSE

                           这个选项允许编写可读性更强的正则表达式代码,并进行自由的格式化操作。

                           当这个选项被指定以后,在正则表达式之间的空格符会被忽略,除非这个空格符是在一个字符类中[ ],或者在空格前使用一个反斜杠\\。

                           这个选项允许对正则表达式进行缩进,使得正则表达式的代码更加格式化,更加清晰。并且可以在正则表达式的代码中使用注释,这些注释会被正则表达式引擎在处理的时候忽略。

                           注释以\'#\'字符开头。所以如果需要在正则表达式中使用\'#\'符号,需要在前面添加反斜杠\'\\#\'或者将它放在[]中,[#]。

charref = re.compile(r"""
&[#]                # Start of a numeric entity reference
(
     0[0-7]+         # Octal form
   | [0-9]+          # Decimal form
   | x[0-9a-fA-F]+   # Hexadecimal form
)
;                   # Trailing semicolon
""", re.VERBOSE)

如果没有指定re.**VERBOSE**选项,则相当于:
charref
= re.compile("&#(0[0-7]+" "|[0-9]+" "|x[0-9a-fA-F]+);")

使用pattern实例来进行匹配

match()    从字符串指定位置开始匹配,匹配到就停止,返回match对象

    match(string[, pos[, endpos]]) --> match object or None.

    Matches zero or more characters at the beginning of the string

search()   从字符串指定位置之后的任意位置开始匹配,匹配到就停止,返回Match对象

    search(string[, pos[, endpos]]) --> match object or None.

    Scan through string looking for a match, and return a corresponding match object instance. Return None if no position in the string matches.

findall()    从字符串指定位置之后的任意位置开始匹配,匹配到了继续匹配,返回字符串中所有匹配的字符串组成的列表。

注意:如果正则表达式中有()分组,则findall返回的是被()括起来的分组字符串所组成的列表。

    findall(string[, pos[, endpos]]) --> list.

    Return a list of all non-overlapping matches of pattern in string.

finditer()  从字符串指定位置之后的任意位置开始匹配,匹配到了继续匹配,返回一个包含了所有的Match对象的迭代器

    finditer(string[, pos[, endpos]]) --> iterator.

    Return an iterator over all non-overlapping matches for the RE pattern in string. For each match, the iterator returns a match object.

sub()         将字符串通过正则表达式匹配到的字符使用repl进行制定次数的替换(默认全部替换),repl可以是字符串,也可以使方法名。

当为方法名时,repl方法接收匹配到的match对象,且该sub()方法返回repl方法的返回值

    sub(repl, string[, count = 0]) --> newstring

    Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl.

split()        将字符串通过正则表达式匹配到的字符进行指定次数的分割(默认全部),返回分割后的列表

    split(string[, maxsplit = 0])  --> list.

    Split string by the occurrences of pattern.

# 导入re模块

>>> import re

# 生成pattern对象
>>> pa=re.compile(r\'(ddd)\')

# 使用pattern对象通过match方法进行匹配得到match对象
>>> ma=pa.match(\'dddsssdddsssddd\\ndddsssdddsssddd\',5) >>> ma.groups() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: \'NoneType\' object has no attribute \'groups\'
# 使用pattern对象通过search方法进行匹配得到match对象
>>> ma=pa.search(\'dddsssdddsssddd\\ndddsssdddsssddd\',5)

>>> ma.groups()

(\'ddd\',)
# 使用pattern对象通过findall方法进行匹配得到匹配到的字符串所组成的列表
>>> ma=pa.findall(\'dddsssdddsssddd\\ndddsssdddsssddd\',5) 

>>> ma [\'ddd\', \'ddd\', \'ddd\', \'ddd\', \'ddd\']

# 使用pattern对象通过finditer方法进行匹配得到匹配到的Match对象所组成的迭代器
>>> for i in pa.finditer(\'dddsssdddsssddd\\ndddsssdddsssddd\',5): 

...   
print i

...

<_sre.SRE_Match object at 0x0000000002607378>

<_sre.SRE_Match object at 0x0000000002544F30>

<_sre.SRE_Match object at 0x0000000002607378>

<_sre.SRE_Match object at 0x0000000002544F30>

<_sre.SRE_Match object at 0x0000000002607378>
# 使用pattern对象通过sub方法进行替换得到替换后的新字符串
>>> ma=pa.sub(\'aaa\',\'dddsssdddsssddddddsssdddsssddd\') 

>>> print type(ma),ma

<type \'str\'> aaasssaaasssaaaaaasssaaasssaaa

>>> ma=pa.sub(\'aaa\',\'dddsssdddsssddddddsssdddsssddd\',2)

>>> print type(ma),ma

<type \'str\'> aaasssaaasssddddddsssdddsssddd

>>> def upper_str(match):

...   
return match.group().upper()

...

>>> ma=pa.sub(upper_str,\'dddsssdddsssddddddsssdddsssddd\',2)

>>> print type(ma),ma

<type \'str\'> DDDsssDDDsssddddddsssdddsssddd
# 使用pattern对象通过sub方法进行分割,得到分割后的字符串组成的列表
>>> ma=pa.split(\'dddsssdddsssddddddsssdddsssddd\',2) 

>>> print type(ma),ma

<type \'list\'> [\'\', \'sss\', \'sssddddddsssdddsssddd\']

>>> ma=pa.split(\'dddsssdddsssddddddsssdddsssddd\')

>>> print type(ma),ma

<type \'list\'> [\'\', \'sss\', \'sss\', \'\', \'sss\', \'sss\', \'\']

匹配对象属性

group()    返回正则表达式匹配到的字符串

groups()  返回正则表达式匹配到的字符串构成的元组。注意:如果正则表达式中有()分组,则groups()中是被()括起来的分组字符串所组成的列表。

>>> ma = re.match(r\'[\\w]{6,11}@(163|qq|huawei)(163|qq|huawei)\\.com\\1\\2\',\'yc123456@163qq.com163qq\')

>>> ma.group()

\'yc123456@163qq.com163qq\'

>>> ma.groups()

(\'163\', \'qq\')

start()       返回匹配的起始位置

end()        返回匹配的结束位置

span()      返回一个包含匹配的起始位置和结束位置的元组(start, end)

string       进行匹配的源字符串

ma.re       进行匹配的正则表达式

3.正则表达式基本语法

匹配单个字符

.    匹配任意字符,除了\\n

[...]    匹配字符集。如[a-z]

\\d|\\D    匹配数字|非数字

\\s|\\S    匹配空白|非空白

\\w|\\W    匹配word字符|非word字符。[a-zA-Z0-9]

\\[\\]    匹配字符串中的[]

匹配多个字符

*    匹配前一个字符0次或无限次

+    匹配前一个字符1次或无限次。如匹配有效标识符r\'[_a-zA-Z]+\\w\'

?    匹配前一个字符0次或1次。如匹配两位数r\'[1-9]?[0-9]\'。注:09的匹配结果是0

{m}|{m,n}    匹配前一个字符m次或者m到n次。如匹配qq邮箱r\'\\w{6,10}@qq.com\'

*? |+? |??    *、+、?的匹配模式变为非贪婪模式。即返回的匹配结果会是最少的。

>>> re.findall(r\'[0-9]k*\',\'1kkkk\')

[\'1kkkk\']

>>> re.findall(r\'[0-9]k*?\',\'1kkkk\')

[\'1\']

>>> re.findall(r\'[0-9]k?\',\'1kkkk\')

[\'1k\']

>>> re.findall(r\'[0-9]k??\',\'1kkkk\')

[\'1\']

>>> re.findall(r\'[0-9]k+\',\'1kkkk\')

[\'1kkkk\']

>>> re.findall(r\'[0-9]k+?\',\'1kkkk\')

[\'1k\']

边界匹配

^    匹配字符串开头

$    匹配字符串结尾

\\A|\\Z    指定的字符串必须为开头|结尾

>>> re.findall(r\'\\A[0-9].*k\\Z\',\'1kkkk\')

[\'1kkkk\']

>>> re.findall(r\'\\A[0-9].*k\\Z\',\'1kkkz\')

[]

分组匹配

|    匹配左右任意一个表达式。如匹配0~100:r\'^[0-9]$|^[1-9][0-9]$|^100$\'

>>> re.findall(r\'^[0-9]$|^[1-9][0-9]$|^100$\',\'100\')

[\'100\']

>>> re.findall(r\'^[0-9]$|^[1-9][0-9]$|^100$\',\'9\')

[\'9\']

>>> re.findall(r\'^[0-9]$|^[1-9][0-9]$|^100$\',\'99\')

[\'99\']

>>> re.findall(r\'^[0-9]$|^[1-9][0-9]$|^100$\',\'09\')

[]    单字符集。

(ab)    括号中的表达式作为一个分组。

从左到右按顺序为1,2,3。常用于不同的个别单词。如匹配163邮箱和qq邮箱:r\'\\w{6,11}@(163|qq|huawei).com\'

>>> re.match(r\'[\\w]{6,11}@(163|qq|huawei)\\.com\',\'yc123456@163.com\').group()

\'yc123456@163.com\'

>>> re.match(r\'[\\w]{6,11}@(163|qq|huawei)\\.com\',\'yc123456@qq.com\').group()

\'yc123456@qq.com\'

>>> re.match(r\'[\\w]{6,11}@(163|qq|huawei)\\.com\',\'yc123456@huawei.com\').group()

\'yc123456@huawei.com\'

\\<number>    引用编号为num的分组匹配到的字符串。类似于管道命令中的xargs -i。

注:\\1对应第一个()所匹配到的字符串。如果只有1个分组(),但是使用\\2,则会报错。如用来匹配XML文件

>>> re.match(r\'<(\\w+>).*</\\1\',\'<book>test</book>\').group()

\'<book>test</book>\'

>>> re.match(r\'<(\\w+>).*</\\1\',\'<book>test</ebook>\').group()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: \'NoneType\' object has no attribute \'group\'

>>> re.match(r\'<(\\w+>).*</\\1\',\'<book>test</book1>\').group()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: \'NoneType\' object has no attribute \'group\'

(?P<name>)    给分组起别名

(?P=name)    引用起过别名的分组

>>> re.match(r\'[\\w]{6,11}@(?P<type1>163|qq|huawei)(?P<type2>163|qq|huawei)\\.com(?P=type1)(?P=type2)\',\'yc123456@163qq.com163qq\').group()

\'yc123456@163qq.com163qq\'

>>> re.match(r\'[\\w]{6,11}@(?P<type1>163|qq|huawei)(?P<type2>163|qq|huawei)\\.com(?P=type1)(?P=type2)\',\'yc123456@163qq.com163163\').group()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: \'NoneType\' object has no attribute \'group\'

以上是关于Python 正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

python 正则表达式

python成长之路第三篇_正则表达式

python成长之路第三篇_正则表达式

python 正则表达式 re模块基础

Python学习笔记之正则表达式

python基础学习(十三)