Python中的正则表达式

来源:互联网 发布:淘宝虚假发货如何辨别 编辑:程序博客网 时间:2024/05/20 23:33

正则表达式是描述字符串排列的一套规则,它主要用于字符串的匹配。在Python中,我们一般使用re模块实现正则表达式的功能。
1.原子
原子是正则表达式中最基本的组成单位,常见的原子有普通字符、非打印字符、通用字符、原子表等。
(1)普通字符作为原子
普通字符如数字、大小写字母、下划线等都可以作为原子使用。在下面的程序中,我们首先导入了re模块,然后把”bai”赋值给变量pattern,这里有3个原子,分别为’b’,’a’,’i’。随后我们定义了变量string,利用re模块里的search()函数从字符串string中去匹配对应的正则表达式,执行结果在程序下方。可以看到,我们成功的在string找到了对应的pattern。

import repattern = "bai"string = "www.baidu.com"result = re.search(pattern, string)result
<_sre.SRE_Match object; span=(4, 7), match='bai'>

(2)非打印字符作为原子
所谓非打印字符,指的是在一些字符串中用于格式控制的符号,比如换行符、回车符等。常见的非打印字符如下表所示。

字符含义\n匹配一个换行符\f匹配一个换页符\r匹配一个回车符\t匹配一个制表符\v匹配一个垂直制表符

下面的程序用于匹配string中的换行符。

pattern = "\n"string = '''www.baidu.comwww.taobao.com'''result = re.search(pattern,string)result
<_sre.SRE_Match object; span=(13, 14), match='\n'>

(3)通用字符作为原子
通用字符,即一个原子可以匹配一类字符。常见的通用字符及含义如下表所示。

字符含义\w匹配任意一个字母、数字或下划线\W匹配除字母、数字和下划线以外的任意字符\d匹配任意一个十进制数字\D匹配除十进制数字以外的任意一个其他字符\s匹配任意一个空白字符\S匹配除空白字符以外的任意一个其他字符

比如,我们可以用”\w\dpython\w”来对”python”字符进行匹配,字符前一位是一个任意的十进制数,再前一位是一个字母、数字或下划线,字符后一位是一个字母、数字或下划线。如”a7python8”、”u2python_”等均可以匹配成功。

pattern = "\w\dpython\w"string = "abcdefg444python___"result = re.search(pattern, string)result
<_sre.SRE_Match object; span=(8, 17), match='44python_'>

运行上面的程序,我们可以看到匹配的结果是’44python_’。
(4)原子表
使用原子表,可以定义一组地位平等的原子,然后匹配的时候会去该原子表的任意一个原子进行匹配。在Python中,原子表由[]表示,比如[xyz]就是一个原子表,这个原子表中定义了3个原子,这3个原子的地位平等。例如我们定义正则表达式为”[xyz]py”,源字符串为”xpython”,如果此时使用re.search()函数进行匹配,就可以匹配出结果”xpy”。类似的,[^]代表的是中括号里面的原子不尽兴匹配,而其他原子进行匹配。如”[^xyz]py”能匹配”apy”但不能匹配”xpy”。

pattern1 = '\w\dpython[xyz]\w'pattern2 = '\w\dpython[^xyz]\w'pattern3 = '\w\dpython[xyz]\W'string = 'abcdefg123python_py'result1 = re.search(pattern1, string)result2 = re.search(pattern2, string)result3 = re.search(pattern3, string)print(result1)print(result2)print(result3)
None<_sre.SRE_Match object; span=(8, 18), match='23python_p'>None

可以看出,程序中的result2匹配成功,匹配结果是”23python_p”,而result1和result3均没有匹配成功。
2.元字符
所谓元字符,就是正则表达式中具有特殊含义的一些字符,如重复N次前面的字符等。元字符可分为:任意匹配元字符、边界限制元字符、限定符等。常见的元字符如下表所示。

字符含义.匹配除换行符以外的任意字符^匹配字符串的开始位置$匹配字符串的结束位置*匹配0次、1次或多次前面的原子,等价于{0,}?匹配0次或1次前面的原子,等价于{0,1}+匹配1次或多次前面的原子,等价于{1,}{n}n是一个非负整数,恰好匹配n次前面的原子{n,}n是一个非负整数,至少匹配n次前面的原子{n,m}n和m均为非负整数,最少匹配n次且最多匹配m次前面的原子x | y匹配x或y(pattern)匹配pattern并获取这一匹配

(1)任意匹配元字符
我们可以使用’.’来匹配一个除换行符以外的任意一个字符。示例程序如下:

pattern = '.python.'string = '''abcdefpythonaapythonb'''result = re.search(pattern, string)result
<_sre.SRE_Match object; span=(14, 22), match='apythonb'>

在上面的程序中,我们使用’.python.’匹配一个’python’前面有1位且后面也有1位除换行符外的任意字符的字符串。可以看到,最后匹配的结果是’apythonb’,没有匹配到’fpython\n’。
(2)边界限制元字符
我们可以使用’^’来匹配字符串的开始位置,用’$’匹配字符串的结束位置。示例如下:

pattern1 = '^abc'pattern2 = '^abd'pattern3 = 'abc$'pattern4 = 'abd$'string = 'abcdeabc'result1 = re.search(pattern1, string)result2 = re.search(pattern2, string)result3 = re.search(pattern3, string)result4 = re.search(pattern4, string)result5 = re.search(pattern5, string)print(result1)print(result2)print(result3)print(result4)
<_sre.SRE_Match object; span=(0, 3), match='abc'>None<_sre.SRE_Match object; span=(5, 8), match='abc'>None

上面的程序中,只有pattern1和pattern3匹配成功了,pattern2和pattern4没有匹配成功。这是因为pattern2限制了字符串必须以’abd’开头,pattern4限制了字符串必须以’abd’结尾,而源字符串是以’abc’开头且以’abc’结尾的,所以pattern2和pattern4无法匹配成功。
(3)限定符
限定符涌来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配,限定符有*、+、?、{n}、{n,}和{n,m}共6种。接下来通过一个示例程序分析限定符的使用。

pattern1 = 'py.*n'pattern2 = 'cd{2}'pattern3 = 'cd{3,}'pattern4 = 'ab{1,2}'pattern5 = '(ab){1,2}'string = 'abbcddddpythonabb'result1 = re.search(pattern1, string)result2 = re.search(pattern2, string)result3 = re.search(pattern3, string)result4 = re.search(pattern4, string)result5 = re.search(pattern5, string)print(result1)print(result2)print(result3)print(result4)print(result5)
<_sre.SRE_Match object; span=(8, 14), match='python'><_sre.SRE_Match object; span=(3, 6), match='cdd'><_sre.SRE_Match object; span=(3, 8), match='cdddd'><_sre.SRE_Match object; span=(0, 3), match='abb'><_sre.SRE_Match object; span=(0, 2), match='ab'>

在上面的程序中,5个正则表达式全部成功匹配,但是匹配结果有所不同。在pattern1中,我们设置的格式是’py’和’n’之间可以出现0次、1次或多次除换行符以外的任意字符,所以匹配出了’python’;pattern2则要求’c’后面的字符’d’恰好出现两次(注意不是’cd’恰好出现两次),所以匹配结果是’cdd’;在pattern3中,要求’c’后面的’d’至少出现3次,此时在满足格式的基础上会在源字符串中尽可能多的匹配字符,所以匹配结果是’cdddd’,其中’c’后面的’d’出现了4次;pattern4要求’a’后面的’b’至少出现1次,至多出现2次,这里同样会尽可能多的匹配字符,所以匹配结果是’abb’;在pattern5中,我们把’ab’当成一个原子,要求它在源字符串中至少出现1次,至多出现2次,所以匹配结果与pattern4的结果不同,只匹配了’ab’。
3.模式修正
模式修正就是可以在不改变正则表达式的情况下,通过模式修正符改变正则表达式的含义,从而实现匹配结果的调整。比如,我们可以用模式修正符’I’让匹配时不再区分大小写。常见的模式匹配符如下表所示。

字符含义I匹配时忽略大小写M多行匹配L本地化识别匹配U根据Unicode字符解析字符S让’.’匹配包括换行符的任意字符
pattern1 = 'python'pattern2 = 'PYTHON.'string = '''xyzPYTHONabcpython'''result1 = re.search(pattern1, string)result2 = re.search(pattern1, string, re.I)result3 = re.search(pattern2, string)result4 = re.search(pattern2, string, re.S)print(result1)print(result2)print(result3)print(result4)
<_sre.SRE_Match object; span=(13, 19), match='python'><_sre.SRE_Match object; span=(3, 9), match='PYTHON'>None<_sre.SRE_Match object; span=(3, 10), match='PYTHON\n'>

在上面的程序中,我们先让pattern1匹配string,匹配结果是’python’,接着我们忽略大小写进行匹配,这一次的匹配结果是’PYTHON’;然后让pattern2去匹配string,匹配结果是None,第二次匹配我们把’.’设置成可以匹配成换行符的模式,这时我们就可以匹配到’PYTHON\n’了。
4.贪婪模式和懒惰模式
+、*和?等限定符都是贪婪的,因为他们会尽可能多的匹配文字,只要在它们后面加上一个?就可以实现非贪婪匹配。

pattern1 = 'p.*y'pattern2 = 'p.*?y'pattern3 = 'p.{2,}?y'string = 'abcdphp123python_py'result1 = re.search(pattern1, string)result2 = re.search(pattern2, string)result3 = re.search(pattern3, string)print(result1)print(result2)print(result3)
<_sre.SRE_Match object; span=(4, 19), match='php123python_py'><_sre.SRE_Match object; span=(4, 12), match='php123py'><_sre.SRE_Match object; span=(4, 12), match='php123py'>

在上面的程序中,贪婪模式的匹配结果是’php123python_py’,而非贪婪模式的匹配结果则是’php123py’,明显比贪婪模式要短。
5.正则表达式常见函数
(1)re.match()函数
如果想要从源字符串的起始位置匹配一个模式,我们可以使用re.match()函数,该函数的使用格式是:
re.match(pattern, string, flag)
其中第一个参数对应模式字符串,第二个参数是源字符串,第三个参数是可选的,代表对应的标志位,可以传递模式修正符等信息。

pattern1 = 'python'pattern2 = '.python'string = 'apythonbbb'result1 = re.match(pattern1, string)result2 = re.match(pattern2, string)print(result1)print(result2)
None<_sre.SRE_Match object; span=(0, 7), match='apython'>

上面的程序中,匹配会在源字符串的起始位置进行。由于pattern1的起始字符无法和string的起始字符对应,所以没有匹配成功。
(2)re.search()函数
re.search()函数会在全文进行检索并匹配,即它要扫描整个字符串。之前已经使用过这个函数,在此就不再举例了。
(3)全局匹配函数
在之前的例子中,我们发现,即使源字符串中存在多个结果符合模式,也只匹配第一个结果,那么如何将符合模式的串全部输出呢?我们可以先用re.compile()函数对模式进行预编译,然后使用findall()函数根据模式从源字符串中将匹配结果全部找出。

pattern = 'python'string = 'pythonaaapythonbbbpython'result = re.compile(pattern).findall(string)print(result)
['python', 'python', 'python']

(4)re.sub()函数
我们可以通过re.sub()函数来实现根据模式串替换源字符串某些字符的功能。re.sub()函数使用格式如下:
re.sub(pattern, rep, string, max)
其中,第一个参数对应模式串,第二个参数是要替换成的字符串,第三个参数是源字符串,最后一个参数是可选的,代表最多替换的次数,如果不写就是全部替换。

pattern = 'python'rep = 'php'string = 'python is the best parogramming language'result = re.sub(pattern, rep, string)print(result)
php is the best parogramming language

可以看到,上面程序中的’python’已经被替换成了’php’。

原创粉丝点击