python正则表达式使用


前言

在文本中,我们常常需要查找特定的字符串。比如分析日志时我们会更加关注ERROR字样,然后定位到相关的位置。当然一个ctrl + F足以满足我们的需要,但是当我们需要找到以ERROR开头的行时,我们又该怎么做呢?普通的查找会将ERROR位于中间的行一并查找出来。只有正则表达式能够满足我们的要求。


一、正则表达式是什么?

正则表达式是一门编程语言,用户根据正则表达式的语法编写特定的模式,然后去匹配或者不匹配特定的字符串。我们最常用的查找某个字符串就是最简单的正则表达式。更进一步,我们需要查找某一类的字符串,就需要提取这类字符串的共同特征,然后利用正则表达式语法编写成特定的模式。

二、正则表达式的基础

1.高频用法

语法效果
.点号,匹配除换行符外任意一个字符(注意:一个点号就是匹配一个字符)
*将前一个规则匹配0次或者多次(记住的办法:0乘以任何数都是0 )
+将前一个规则匹配1次或者多次
\d匹配一个数字
\w匹配任意单词的字元素(此处单词的定义:字母、数字和下划线元素的组合)
[a,b,c]匹配a、b、c中任意一个字母,类似枚举
[a-z, A-Z]匹配26个字母,忽略大小写
{n, m}匹配前一个规则n次到m次
{n, }匹配前一个规则至少n次
{n }匹配前一个规则n次
?匹配前一个规则0次或者1次(具体含义下文例子)
\s匹配空白字符,包括换行符
\S大写S,匹配非空白字符
^a匹配a开头的字符串
z$匹配z结尾的字符串
[^a,b]不能匹配a和b字符

如上表格中总结了正则表达式的高频基础用法,掌握上述用法足可以应对80%的正则表达式。

读者此时可以根据上述规则每个都尝试一遍,有助于记忆。正则匹配可视化工具:https://www.jyshare.com/front-end/854/?optionGlobl=global

在这里插入图片描述

2.捕获分组

正则表达式的应用一般有两种,一种是校验某种字符串是否合法,比密码长度、IP字符串等,第二种就是提取特定的字符串。捕获分组可以帮我们实现这个功能。
比如我们需要匹配一个回文字符串。
在这里插入图片描述

其中\1表示捕获的第一个分组。
另外,分组既然是括号来表示,那么也具有括号的普通功能,即将其视为一个整体。
在这里插入图片描述

上述图片中匹配文本没变色表示模式没匹配中。

三、Python使用正则表达式

1.search函数

import re

m = re.search(r"(\d+)\s+(\w+)", "5 apples and 1 banana and 2 apples.")
print(m)
# <re.Match object; span=(0, 8), match='5 apples'>
# 没有匹配到2 apples,说明只匹配一次

print("m.group():", m.group())
# m.group(): 5 apples 结论:group表示正则表达式匹配的整体

print("m.group(0):", m.group(0))
# m.group(0): 5 apples 结论:group(0) == group()

print("m.group(1):", m.group(1))
# m.group(1): 5 结论:group(1)表示第一个捕获的分组

print("m.group(2):", m.group(2))
# m.group(2): apples 结论:group(2)表示第二个捕获的分组

print("m.group(1,2):", m.group(1, 2))
# m.group(1,2): ('5', 'apples') 结论:group(1, 2)表示第一、二个捕获的分组,返回元组形式

print("m.groups():", m.groups())
# m.groups(): ('5', 'apples') 结论:groups()表示所有捕获的分组

2.finditer函数

import re

m = re.finditer(r"(\d+)\s+(\w+)", "5 apples and 1 banana and 2 apples.")

for item in m:
    print(item)

# 输出
# <_sre.SRE_Match object; span=(0, 8), match='5 apples'>
# <_sre.SRE_Match object; span=(13, 21), match='1 banana'>
# <_sre.SRE_Match object; span=(26, 34), match='2 apples'>
# 根据输出结果,可以发现finditer可以匹配多次
# 其中m表示一个迭代器


m = re.findall(r"(\d+)\s+(\w+)", "5 apples and 1 banana and 2 apples.")

for span in m:
    print(span)

# 输出
# ('5', 'apples')
# ('1', 'banana')
# ('2', 'apples')
# 在finditer的基础上,获取每个匹配对象(item)的所有捕获分组

3.match函数

origin = "I have 5 apples and 1 banana and 2 apples."
m = re.match(r"(\d+)\s+(\w+)", origin)

print(m)
# 输出是None,注意match必须从origin字符串开头进行匹配,类似于str.startswith()函数

m = re.fullmatch(r"(\d+)\s+(\w+)", "5 apples and 1 banana and 2 apples.")

print(m)
# 输出是None,因为fullmatch必须全匹配,类似于==

4.字符转义

origin = "\\"
m1 = re.fullmatch("\\\\", origin)
print(m1)
# <_sre.SRE_Match object; span=(0, 1), match='\\'>

m2 = re.fullmatch(r"\\", origin)
print(m2)
# <_sre.SRE_Match object; span=(0, 1), match='\\'>

# 结论想要匹配反斜杠字符,要么使用四个\\\\,要么使用r开头

上述代码的原因在于字符转义。因为Python解释器和正则引擎都会对反斜杠做特殊的处理。

  1. 代码中的\在Python中本身就不会被直接输出,反斜杠和n组成换行符,要想python解释器将反斜杠当成一个普通的字符,需要双反斜杠进行转义。这就是origin变量中用双反斜杠表示反斜杠字符的原因。
  2. 但是,反斜杠在正则表达式中还是有特殊含义,比如\d,所以还要进行一次转义,所以就是四个反斜杠了。

r字符的含义就是告诉Python解释器把这些字符当成普通字符即可。
第一次接触match、search、find时很容易搞混每种函数的作用,但是转念一想,三个函数名称的语义已经暗含了这个意思:
匹配:鞋子匹不匹配肯定是从脚尖或者脚后跟开始比较,只要鞋子略长于脚即可,一般不会刚刚好(fullmatch)
搜索:第一个匹配了我就返回了,因为搜索到了
查找:必须找到全部匹配的,因为是查找,必须搞清有多少个

5、修饰符

m = re.match("A", "a", re.I)
print(m)
# 输出
# <_sre.SRE_Match object; span=(0, 1), match='a'>
# re.I是正则表达式的额外匹配策略,I表示ignore忽略大小写进行匹配

m = re.match(".", "\n", re.S)
print(m)
# <_sre.SRE_Match object; span=(0, 1), match='\n'>
# 结论:re.S使得.号可以匹配换行符

m = re.search("^X", "A\nB\nX", re.MULTILINE)
print(m)
# 输出
# <_sre.SRE_Match object; span=(4, 5), match='X'>
# 表面看上去X是在字符串中间,不是在开头,所以^X无法匹配,但是因为`re.MULTILINE`导致^去匹配每一行的开头,而非整个字符串开头

总结

本文仅仅简单介绍了正则表达式的基础用法,然后结合python编程语言的re模块举了几个例子。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值