python中的正则表达式

2020-05-07 16:32:52 浏览数 (1)

则表达式, 是一门独立的搜索和匹配字符串的语言,只不过在各种编程语言中得到了实现,其中perl语言的正则表达式堪称是范本,很多其他编程语言都参考perl的正则语法来实现。python中的正则表达式通过内置模块re来实现,与perl的正则表达式操作类似,如果你熟悉perl语言的话,对于python的正则也可以轻松上手。

基本用法如下

代码语言:javascript复制
>>> a = re.search(r'c','abc123')
>>> a
<re.Match object; span=(2, 3), match='c'>

其中r前缀指定的字符串称之为正则表达式的pattern, 后面是需要待匹配的字符串,正则的搜索引擎会从字符串的开头进行查找,来找出符合条件的字符, 上述例子从字符串abc123的开头进行查找,查找特定的字符c

对于正则表达式,有以下几个基础概念

1. 字符集

正则的基本作用是匹配字符串,在开头的例子中用指定字符来进行匹配,这样无疑更加精确,但是缺少灵活性,比如匹配以下两个字符中的数字

abc123 abc456

如果用指定数字的方式来匹配,上述两个字符的匹配就要写成两种

re.search(r’123’,’abc123’) re.search(r’456’,’abc456’)

这样显然太局限了,为了更加通用,提出了字符集的概念,事先定义了几种匹配常用字符的字符集

  • d , 匹配一个0到9之间的数字
  • w, 匹配数字,字母,下划线中的任意一个字符
  • s, 匹配任意一个空白字符,即rbntf中的任意一个,
  • D , 匹配任意一个非数字的字符
  • W, 匹配任意一个非数字,字母,下划线中的字符
  • `S, 匹配任意一个非空白字符
  • ., 点号,默认匹配任意一个非换行符的字符

对应的字符大写之后,可以看做相反的集合。另外,也支持通过方括号来自定义字符集合,用法如下

代码语言:javascript复制
# 相当于d
[0-9]
# 相当于w
[A-Za-z0-9_]
# 相当于s
[rntf]

用字符集再来匹配上述例子,写法如下

re.search(r’ddd’,’abc123’) re.search(r’ddd’,’abc456’)

这样用同一个正则就可以了。

2. 量词

从基本用法也可以看出,默认情况下,一个字符集只匹配一个字符,为了匹配变长的情况,比如匹配以下两个字符串中的数字

abc123 abc1234

在正则的pattern后面可以添加量词,控制正则匹配的次数,常用的量词如下

  1. *匹配0或者任意次
  2. 匹配1或者任意次
  3. ?匹配0到1次
  4. {m}, 匹配m次
  5. {m} : 匹配m次以以上
  6. {m,n}:匹配m到n次

用量词,上述匹配写法如下

re.search(r’d ’,’abc123’) re.search(r’d ’,’abc1234’)

用了量词之后,更加通用。默认情况下,量词为贪婪匹配,即匹配最长的符合模式的字符,看下面的例子

代码语言:javascript复制
>>> re.search(r'[w;] ;','abc;123;123')
<re.Match object; span=(0, 8), match='abc;123;'>

用了加号的情况下,匹配到了第二个分号,此时如果只需要匹配到第一个分号,我们可以在量词的后面添加?, 使其变为非贪婪匹配,写法如下

代码语言:javascript复制
>>> re.search(r'[w;] ?;','abc;123;123')
<re.Match object; span=(0, 4), match='abc;'>

可以看到,在非贪婪匹配中,遇到第一个符合模式的字符,程序就停止了,不会继续往后查找,而默认的贪婪模式会接着往下检索。

3. 位置限定符

默认情况下,正则从字符串开头进行检索,寻找任意位置符合模式的字符。但有时我们需要匹配字符的位置进行限定,比如匹配以下字符串末尾的数字

123abc123

此时,我们就需要用到位置限定符号,也叫做锚定符,常用的如下

  1. ^匹配字符串开头
  2. $匹配字符串末尾
  3. A匹配字符串开头
  4. Z匹配字符串末尾
  5. b, 单词的边界
  6. B, 非单词的边界

用锚定符,上述匹配的写法如下

re.search(r’d $’,’123abc123’)

4. 模式修饰符

修饰符影响正则的匹配行为,常用的修饰符如下

  1. re.I, 不区分大小写的匹配
  2. re.S, 此时点号也可以匹配换行符
  3. re.M, 多行匹配

修饰符的用法示意如下

re.search(r’ABC’,’123abc’, re.I)

除了上述写法,也支持以下写法

re.search(r’(?i)ABC’,’123abc’) re.search(r’(?i:ABC)’,’123abc’)

在圆括号中的问号后面添加修饰符,i对应re.I。正则表达式在实际开发中常见用途如下

1. 条件判断

查看字符串是否匹配特定模式, 常用作逻辑判断语句,用法如下

代码语言:javascript复制
if re.search(r'd ','abc123'):
    print("success")
else:
    print("failed")

2. 提取符合模式的字符串

通过在模式的两端添加圆括号,可以捕获对应的字符,用法如下

代码语言:javascript复制
# 在正则中使用圆括号进行捕获
>>> re.search(r'(abc)(123)','abc123')
<re.Match object; span=(0, 6), match='abc123'>
#  groups函数返回捕获元素的元组
>>> re.search(r'(abc)(123)','abc123').groups()
('abc', '123')
# group函数默认值为0
>>> re.search(r'(abc)(123)','abc123').group()
'abc123'
# 下标0返回原始待匹配字符串
>>> re.search(r'(abc)(123)','abc123').group(0)
'abc123'
# 下标1返回第一个捕获的字符串
>>> re.search(r'(abc)(123)','abc123').group(1)
'abc'“”
# 下标2返回第二个捕获的字符串
>>> re.search(r'(abc)(123)','abc123').group(2)
'123'
3, 替换特定字符串

通过re.sub函数来特换特定字符串,用法如下

代码语言:javascript复制
>>> re.sub(r'abc', 'ABC', 'abc123abc')
'ABC123ABC'
>>> re.sub(r'abc', 'ABC', 'abc123abc', count = 1)
'ABC123abc'

返回值为替换后的字符串,count参数控制替换的次数,默认值为0,表示全部替换。除此之外,还有一个re.subn函数,返回值为替换后的字符串和替换次数构成的元组,用法如下

代码语言:javascript复制
>>> re.subn(r'abc', 'ABC', 'abc123abc')
('ABC123ABC', 2)
3. 灵活的分隔字符串

字符串自带的split方法只允许以固定字符分隔字符串,用re.split函数,可以用正则来分隔字符串,更加灵活,用法如下

代码语言:javascript复制
>>> re.split(r'[:=]', 'A=B:C')
['A', 'B', 'C']
4. 查找特定字符串

通过re.findall函数,查找所有符合模式的字符串,用法如下

代码语言:javascript复制
>>> re.findall(r'd ', '123abc123abc123')
['123', '123', '123']

返回值为一个列表,与之对应的还有一个re.finditer函数,返回值为迭代器,用法如下

代码语言:javascript复制
>>> number = re.finditer(r'd ', '123abc123abc123')
>>> for i in number:
...     print(i.group())
...
123
123
123

除了常用的re.search函数外,还有一个re.match函数,该函数只支持从字符串开头进行匹配,示意如下

代码语言:javascript复制
# 数字不在开头,没有结果
>>> re.match(r'd ', 'abc123')
# 在开头有数字,给出匹配结果
>>> re.match(r'd ', '123abc')
<re.Match object; span=(0, 3), match='123'>
# search更加灵活
>>> re.search(r'd ', 'abc123')
<re.Match object; span=(3, 6), match='123'>

可以看出,相比search, match自动在正则的开始添加^锚定符号,其他行为二者是一样的。

0 人点赞