正则表达式是一个特殊的字符串,可以用来帮我们检查一个字符串是否与给定的模式相匹配,也可以找到目标字符串中匹配给定模式的子字符串。我们先看一个python中使用正则表达式re模块的示例。

import re

pattern = r'小麦'
result = re.match(pattern,'小麦是我')
print(result)
#结果:<re.Match object; span=(0, 2), match='小麦'>
result = re.match(pattern,'我是小麦')
print(result)
#结果:None
可以看到如果匹配成功会返回匹配对象,包括匹配的位置,和匹配的字符串,如果没有匹配到则返回None。pattern就是给定的匹配模式,可以是普通字符,也可以是通用的正则表达式,注意匹配模式最好以r开头,因为我们的许多正则模式都有反斜杠,防止发生转义。下面我们看下常见的正则表达式。
pattern1 = r'^小麦'
print(re.match(pattern1,'小麦是我'))
#结果:<re.Match object; span=(0, 2), match='小麦'>
pattern2 = r'.*小麦$'
print(re.match(pattern2,'我是小麦'))
#结果:<re.Match object; span=(0, 4), match='我是小麦'>
pattern3 = r'\bpy\w*\b'
print(re.match(pattern3,'python'))
#结果:<re.Match object; span=(0, 6), match='python'>

pattern1 = r'\s*\w*'
print(re.match(pattern1,'  python'))
#结果:<re.Match object; span=(0, 0), match='  python'>
pattern2 = r'.*python'
print(re.match(pattern2,'我是小麦学python'))
#结果:<re.Match object; span=(0, 11), match='我是小麦学python'>
pattern3 = r'^[a-z][A-Z]\w*'
print(re.match(pattern3,'pYthon'))
#结果:<re.Match object; span=(0, 6), match='pYthon'>

pattern1 = r'(\w*)@(\w*\.\w*)'
print(re.match(pattern1,'python@python.com').group(1),re.match(pattern1,'python@python.com').group(2))
#结果:python python.com
pattern2 = r'(\d{18})|(^\d{17})(\d|X|x)$'
print(re.match(pattern2,'370102199312250037'))
#结果:<re.Match object; span=(0, 18), match='370102199312250037'>
以上都是匹配成功的正则模式,在python中我们就是利用这些正则表达式来进行匹配、查找、替换。下面我们总结一下常见的正则表达式元素。
#^ 匹配开头
#$ 匹配结尾
#\d 匹配数字
#\w 匹配字母、下划线、数字、汉字
#\W 匹配出\w之外的字母
#. 匹配任意字符
#? 匹配前面的字符出现0次或1次
#+ 匹配前面的字符出现1次或多次
#* 匹配前面的字符出现0次或多次
#[] 匹配中括号里的字符
#[^] 匹配非中括号里的字符
#| 匹配由|拼接的任意一个正则表达式,含义等同于或
#() 分组
正则还有许多的匹配规则,用到的时候可以自己查询,我们下面看下在python中使用正则表达式。
pattern = r'py\w+'
string = 'I like Python Pycharm pYgame'
match = re.search(pattern,string,re.I)
print(match)
#结果:<re.Match object; span=(7, 13), match='Python'>
我们这里使用re对象的search方法,可以看到search不同于match方法,search是在整个字符串中搜索第一个匹配的值,而match是从开始位置匹配,如果匹配失败就返回None。下面我看一下查找字符串中的所有的匹配项findall方法,re.I是方法参数标志,表示忽略大小写(Ignore)。
pattern = r'py\w+'
string = 'I like Python Pycharm pygame'
match = re.findall(pattern,string,re.I)
print(match)
#结果:['Python''Pycharm''pygame']
match = re.findall(pattern,string)
print(match)
#结果:['pygame']
注意这里findall返回的match是一个列表,有关列表我们稍后几节会讲到,下面我们使用这则表达式进行字符串替换操作。
string = '18588885246'
print(re.sub(string[3:-4],'****',string))
#结果:185****5246
string = '18588888888'
print(re.sub(string[3:-4],'****',string,1))
#结果:185****8888
如上,我们讲给定的手机号进行脱敏操作,我们可以利用字符串截取,得到手机号中间4位作为pattern,然后将中间4位替换为*。谨防出现多次替换,我们可以指定替换次数,如上第2个示例,我们指定只替换一次,否则默认为0,表示全部替换,会出现1********的情况。
最后我们看下使用正则表达式进行字符串分割,字符串分割我们在上一节提到过,就是将一个字符串按照指定的字符分割成多个子字符串,使用正则表达式分割就是将字符串按照匹配的模式分割成多个子字符串。
pattern = r'[?|&|#]'
action = 'http://python.com/api?key=int&value=100#1'
print(re.split(pattern,action))
#结果:['http://python.com/api', 'key=int', 'value=100', '1']
print(action.split('?'))
#结果:['http://python.com/api', 'key=int&value=100#1']
可以看到字符串的分割与使用正则表达式分割字符串并没有大的区别,返回的都是列表对象。下一节我们讲运算符。