四、分支条件|
正则表达式也支持类似于OR的方式,使用“|”符号连接几个表达式,只要其中一个表达式匹配上就算匹配。
1
2
3
4
5
6
7
8
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'123|879') #匹配数字123 或者是879
pattern2 = re.compile(r'abcd|gmail') #匹配字符是abcd 或者是gmail
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['123', '879']
['gmail']
|
五、注释(?#…)
(?#…)来表示注释。括号内的内容会被忽视。注释内容并不影响匹配结果,仅仅是说明作用。
1
2
3
4
5
6
7
8
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'123|879(?#匹配数字123 或者是879)')
pattern2 = re.compile(r'abcd|gmail(?#匹配字符是abcd 或者是gmail)')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['123', '879']
['gmail']
|
前面讲过,三重引号的多行字符串,可以添加注释。那么如果把正则表达式写成多行的话,也可以添加注释。这种情况下,需要VERBOSE(也可使用简略写法X)标志,上面的例子可以修改如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = r'''
123 #T注释1 匹配数字123 或者是879
| #T注释2 匹配数字123 或者是879
879 #T注释3 匹配数字123 或者是879
'''
pattern2 = r'''
abcd #T注释1 匹配字符是abcd 或者是gmail
| #T注释2 匹配字符是abcd 或者是gmail
gmail #T注释3 匹配字符是abcd 或者是gmail
'''
item1 = re.findall(pattern1,string,re.VERBOSE)
item2 = re.findall(pattern2,string,re.VERBOSE)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['123', '879']
['gmail']
|
六、贪婪匹配与懒惰匹配
正则表达式默认匹配尽可能多的字符。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern = re.compile(r'\w*t')
item = re.search(pattern,string)
print(item.group())
|
执行以上程序会输出如下结果:
*匹配了尽可能多的字符test,这种匹配模式就被称为贪婪模式。
但是有时候我们的需求是需要匹配尽可能少的字符,这种方式在正则表达式中被成为懒惰模式。需要匹配懒惰模式,只需要在限定符后面加入一个?就可以了。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern = re.compile(r'\w*?t')
item = re.search(pattern,string)
print(item.group())
|
执行以上程序会输出如下结果:
懒惰模式有以下几种形式:
*?重复任意次,但是匹配尽可能少的字符。
+?重复1次或者多次,但是匹配尽可能少的字符。
??重复0次或者1次,但是匹配尽可能少的字符。
{n,}?重复n次以上,但是匹配尽可能少的字符。
{n,m}?重复n次到m次,但是匹配尽可能少的字符。
“*?“的用法:
1
2
3
4
5
6
7
8
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'\w*t')
pattern2 = re.compile(r'\w*?t')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['test']
['t', 'est']
|
”+?“的用法:
1
2
3
4
5
6
7
8
|
import re
string = 'test1234t@gmail.com或13076879876电话'
pattern1 = re.compile(r'\w+t')
pattern2 = re.compile(r'\w+?t')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['test1234t']
['test', '1234t']
|
”??“的用法:
1
2
3
4
5
6
7
8
|
import re
string = 'ttest1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'\w?t')
pattern2 = re.compile(r'\w??t')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['tt', 'st']
['t', 't', 'st']
|
”{n,}?“的用法:
1
2
3
4
5
6
7
8
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'\w{2,}')
pattern2 = re.compile(r'\w{2,}?')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['test1234', 'gmail', 'com或13076879876电话']
['te', 'st', '12', '34', 'gm', 'ai', 'co', 'm或', '13', '07', '68', '79', '87', '6电']
|
”{n,m}?“的用法:
1
2
3
4
5
6
7
8
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'\w{2,4}')
pattern2 = re.compile(r'\w{2,4}?')
item1 = re.findall(pattern1,string)
item2 = re.findall(pattern2,string)
print(item1)
print(item2)
|
执行以上程序会输出如下结果:
1
2
|
['test', '1234', 'gmai', 'com或', '1307', '6879', '876电']
['te', 'st', '12', '34', 'gm', 'ai', 'co', 'm或', '13', '07', '68', '79', '87', '6电']
|
七、分组
分组就是将整个正则表达式分成不同的组,只获取不同组匹配的内容。其中分组使用“()”来区分,括号内匹配的内容为一个组。
示例如下:
1
2
3
4
5
6
7
8
9
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'(test).*(13).*(电话)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string)) #输出[('test', '13', '电话')]。
print('总共匹配到%s个数据。'%len(item1.groups()))
for i in range(len(item1.groups())+1):
print('第%d个数据是:%s'%(i,item1.group(i)))
|
执行以上程序会输出如下结果:
1
2
3
4
5
6
|
[('test', '13', '电话')]
总共匹配到3个数据。
第0个数据是:test1234@gmail.com或13076879876电话
第1个数据是:test
第2个数据是:13
第3个数据是:电话
|
可以看到,(test).(13).(电话)共有三个组,分别匹配了’test’, ‘13’, ‘电话’。
item1的结果是个group组,默认索引从0开始。除了使用数字索引外,还可以重命名组名。
重命名组名(?P<name>pattern)
使用“(?P<name>pattern)”可以重命名组名。
1
2
3
4
5
6
7
8
9
|
import re
string = 'test1234@gmail.com或13076879876电话'
pattern1 = re.compile(r'(?P<第一个匹配项>test).*(?P<第二个匹配项>13).*(?P<第三个匹配项>电话)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string)) #输出[('test', '13', '电话')]。
print(item1.group("第一个匹配项"))
print(item1.group('第二个匹配项'))
print(item1.group('第三个匹配项'))
|
执行以上程序会输出如下结果:
1
2
3
4
|
[('test', '13', '电话')]
test
13
电话
|
八、后向引用
\number
可以用来匹配与某个分组相同的部分,提供查找重复字符组的方便的方法。组从1开始编号,只能用于匹配前99个组中的1个。 如果数字的第一个数字是0,或者数字是3个八进制数字,则不会将其解释为组匹配,而是解释为具有八进制数值的字符。
我们可以通过示例来进行了解。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或test1237@gmail.com或test1289@gmail.com'
pattern1 = re.compile(r'(test\d+).*?(test\d+).*?(test\d+)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string))
|
执行以上程序会输出如下结果:
1
|
[('test1234', 'test1237', 'test1289')]
|
第一组匹配的是test1234
第二组匹配的是test1237
第三组匹配的是test1289
现在来实现第一组和第二组匹配相同的内容,也就是test1234和test1237相同的部分test123。
只需要将第二组的test\d+修改为\1。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或test1237@gmail.com或test1289@gmail.com'
pattern1 = re.compile(r'(test\d+).*?(\1).*?(test\d+)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string))
|
执行以上程序会输出如下结果:
1
|
[('test123', 'test123', 'test1289')]
|
第一组匹配的是test1234
第二组匹配的是test1237
现在来实现第二组和第三组匹配相同的内容,也就是test1237和test1289相同的部分test12。
只需要将第三组的test\d+修改为\2。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或test1237@gmail.com或test1289@gmail.com'
pattern1 = re.compile(r'(test\d+).*?(test\d+).*?(\2)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string))
|
执行以上程序会输出如下结果:
1
|
[('test1234', 'test12', 'test12')]
|
现在来实现第一组,第二组和第三组匹配相同的内容,也就是test1234,test1237和test1289相同的部分test12。
只需要将第二组的test\d+修改为\1,第三组的test\d+修改为\2。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或test1237@gmail.com或test1289@gmail.com'
pattern1 = re.compile(r'(test\d+).*?(\1).*?(\2)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string))
|
执行以上程序会输出如下结果:
1
|
[('test12', 'test12', 'test12')]
|
如果已经给分组进行了命名呢?也没有问题,只需要将代表分组号码的”\1”换为分组名称”?P=…“即可。
(?P=name)
对已命名组的后向引用;它匹配与先前名为name的组匹配的任何文本。
下面第二组引用第一组的名字aaa。需要注意的是,用名字引用的匹配结果是不会显示的。
1
2
3
4
5
|
import re
string = 'test1234@gmail.com或test1237@gmail.com或test1289@gmail.com'
pattern1 = re.compile(r'(?P<aaa>test\d+).*?(?P=aaa).*?(test\d+)')
item1 = re.match(pattern1,string)
print(re.findall(pattern1,string))
|
执行以上程序会输出如下结果:
1
|
[('test123', 'test1289')]
|
第二组的引用’test123’没有显示出来。
转载请注明本网址。