正则表达式
正则表达式是对字符串操作的⼀种逻辑公式,就是⽤事先定义好的⼀些特定字符、及这些特定字符的组合,组成⼀个“规则字符串”,这个“规则字符串”⽤来表达对字符串的⼀种过滤逻辑。
正则的缺点是效率低下,所以能用字符串方法完成尽量使用字符串方法。优点是编码简单。
在python中使用正则,要先导入系统内置模块re。
1.正则表达式的组成
原子是组成正则表达式的最小单位,任何单一字符都可以是正则表达式的一个原子。
除了原子,正则表达式中还有表示特殊含义的特殊原子。下面我不加解释的给与正则表达式中会使用的特殊原子,
除了原子,正则表达式中还有表示个数的量词,我们常用的量词如下,
正则中还有对于正则匹配模式的模式修正符,常用的模式修正符如下,
注意,模式字符串⼀定要使⽤原⽣字符串,也就是⽤r开头的字符串。正则匹配要严格区分⼤写。如果正则表达式中有{,},[,],-,?,*,|^,$,.等做普通字符,则要将其转义。
我们来举一个例子,⽤户名匹配,用户名应由数字、⼤⼩写字⺟、下划线_和中横线-组成,⻓度为4到14位,并且不能以数字开头,
res = re.match(r"[^\d]([a-zA-Z0-9_-]{3,13})", "Forseti_Re")
print(res)
执行结果如下,
<re.Match object; span=(0, 10), match='Forseti_Re'>
2.正则常用方法
2.1.re.match()
re.match()
"""
原型:re.match(pattern, string, flags=0)
功能:从字符串起始位置匹配⼀个模式,如果不是从起始位置匹配则返回None
参数:
patter模式
string要匹配的字符串
flag模式修正符
返回值:匹配成功返回⼀个Match object,失败返回None
"""
例如,
print(re.match(r"Across", "Across the Great Wall"))
print(re.match(r"Across", "Cross the Great Wall"))
print(re.match(r"We", "Across the Great Wall\nWe can reach every corner in the world", re.M)) # 使用多行模式进行匹配
print(re.match(r"^We", "Across the Great Wall\nWe can reach every corner in the world", re.M)) # 使用多行模式进行匹配行首词
执行结果如下,
<re.Match object; span=(0, 6), match='Across'>
None
None
None
我们看到只有第一个匹配成功。最后两个尽管我们使用了\n换行符,但是依然不是字符串的开头。
2.2.re.search()
re.search()
"""
原型:re.search(pattern, string, flags=0)
功能:顺序扫描字符串,找到第⼀个匹配项结束
参数:
patter模式
string要匹配的字符串
flag模式修正符
返回值:匹配成功,返回match object,否则返回None
"""
例如,
print(re.search(r"Great", "Across the Great Wall\nWe can reach every corner in the world"))
res = re.search(r"(\s([a-zA-Z]{6,})\s)", "Across the Great Wall\nWe can reach every corner in the world") # 匹配前后有空格且有六个字母的英文单词
print(res)
执行结果如下,
<re.Match object; span=(11, 16), match='Great'>
<re.Match object; span=(40, 48), match=' corner '>
2.3.re.findall()
re.findall()
"""
原型:findall(pattern, string, flags=0)
功能:扫描整个字符串,并返回结果列表
参数:
patter:匹配的正则表达式
string:要匹配的字符串
flags:模式修正符
返回值:如果匹配成功返回⼀个列表,包含了所有匹配项,失败返回空列表
"""
例如,
print(re.findall(r"a", "Across the Great Wall\nWe can reach every corner in the world"), re.I) # 匹配字符串中所有的a,不区分大小写
res = re.findall(r"\b(\w{4,5})\b", "Across the Great Wall\nWe can reach every corner in the world") # 匹配字符串中所有的4个到5个字母的单词
print(res)
执行结果如下,
['a', 'a', 'a', 'a'] RegexFlag.IGNORECASE
['Great', 'Wall', 'reach', 'every', 'world']
2.4.re.split()
re.split()
"""
原型:split(pattern, string,maxsplit=0,, flags=0)
功能:⽤模式串做分隔符,将字符串分隔,返回分隔列表,如果模式加上括号,则分隔符会被保留
参数:
patter:匹配的正则表达式
string:要匹配的字符串
maxsplit匹配次数,0不限制次数
flags:模式修正符
返回值:成功返回⼦串列表,否则返回空列表
"""
例如,
num = input("请输入三个整数,用逗号或者空格分割:") # 输入整数
res = re.split(r"[,, ]+", num) # 用出现一次或者多次的单个",, (英文空格) (中文空格)"作为分割符,进行字符串分割
res = [int(value) for value in res] # 将列表中的元素转换为int类型
print(sum(res)) # 列表元素求和
注意,这里我们在各个整数之间无论输入多少空格或者逗号,无论是英文还是中文,系统都会进行分割。
2.5.re.sub()
re.sub()
"""
sub(pattern, repl, string, count=0)
功能:在⽬标字符串中以正则表达式的规则匹配字符串,再把他们替换成指定的字符串。可以指定替换的次数,如果不指定,替换所有的匹配字符串
参数:
pattern:正则表达式(规则)
repl:指定的⽤来替换的字符串
string:⽬标字符串
count:最多替换次数
区别:前者返回⼀个替换后的字符串,后者返回⼀个元组,第⼀个元素替换后的字符串,第⼆个元素表示被替换的次数
"""
例如,我们把下划线命名(也叫蛇形命名,所有单词都是⼩写,中间通过下划线连接),转化为⼩驼峰命名法(第⼀个单词⼩写,其余所有单词⾸字⺟⼤写)。例如’go_to_next_page’,转化后改写为’goToNextPage’,
def replace(obj):
# obj.groups(0)[0] # 获取正则表达式截取元组中的下标为0的元素
# obj.groups(0)[1].upper() # 获取正则表达式截取元组中的下标为1的元素并改为大写
return obj.groups(0)[1].upper() # 返回替换字符串
str1 = "go_to_next_page"
res = re.sub(r"([_]{1})(\w)", replace, str1)
print(res)
执行结果如下,
goToNextPage
2.6.re.group()和re.groups()
re.group()和re.groups()⽤于提取⼦元素,模式中⼀个括号就是⼀个⼦元素,group和groups只能在match和search⽅法⾥使⽤,通过返回的match object获取⼦元素。在模式串和sub和subn中的替换字符串中可以使⽤\1,\2,\3…来引⽤⼦元素。
例如,
res = re.search(r"(\d{3,4})-(\d{8})", "010-12345678")
print(res.groups())
print(res.group(1))
print(res.group(2))
执行结果如下,
('010', '12345678')
010
12345678
2.7.re.compile()
re.compile()
"""
原型:re.compile(pattern, flags=0)
功能:将正则表达式模式编译成正则表达式对象,其match()和search()⽅法可⽤于匹配
参数:
pattern模式
flags模式修饰符
"""
当我们使⽤正则表达式时,re模块会⼲两件事:
1.编译正则表达式,如果正则表达式本身不合法,会报错;
2.⽤编译后的正则表达式去匹配对象。
编译正则表达式使⽤compile。
例如,
re_tele = re.compile(r"^1(([3578]\d)|(47))\d{8}$") # 编译正则模式块
print(re_tele.match("13900000000"))~
执行结果如下,
<re.Match object; span=(0, 11), match='13900000000'>