正则表达式常用规则与应用

Posted Python孙行者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式常用规则与应用相关的知识,希望对你有一定的参考价值。

总结一下常见的正则表达式的匹配规则以及常用的方法,匹配中文,标签(应用非贪婪)以及一个较常用的正则匹配规则"?:",方便回顾和查找。

正则表达式基础知识

下面是必须知道与掌握的正则表达式匹配规则

re.compile

compile 函数用于编译正则表达式,生成一个 Pattern 对象

import re

regex = re.compile(r'(\d+)')

re.match

match(string[, pos[, endpos]])方法回从字符串开头开始匹配,也可以指定起始位置和结束位置,找到第一个匹配就返回。成功匹配的话把各分组匹配到的字符串放入到一个Match对象,需要使用group(分组编号)获取对应分组的字符串或使用groups()方法获取所有分组的结果,匹配不成功返回None。

import re

regex = re.compile(r'(\d+)')
str1 = '66abcd78dfg9sdf0'

# match 的使用
result = regex.match(str1)

print(result.groups()) # ('66',)
print(result.group(1)) # 66

但是,match返回的是每个分组的结果,所以必须在正则表达式里带上()进行分组,否则(即一个()分组都没),在存在满足正则表达式的情况下使用groups返回的很有可能是一个空的元组

import re

# 正则没有使用分组
regex = re.compile(r'\d+')
str1 = '66abcd78dfg9sdf0'

# match 的使用
result = regex.match(str1)

print(result.groups()) # ()
print(result.group(1)) #  IndexError: no such group

re.search

search(string[, pos[, endpos]])方法用于查找字符串的任何位置,也可以指定起始和结束位置,只要找到了一个匹配的结果就返回。使用方法和match一样,区别在于match是从字符串开头,search不限定从字符串开头匹配。匹配不成功返回None

import re

regex = re.compile(r'(\d+)')
str1 = 'abcd78dfg9sdf0'

# search 的使用
result = regex.search(str1)

print(result.groups()) # ('78',)
print(result.group(1)) #  78

因为search返回的是每个分组的结果,和match一样,所以必须在正则表达式里带上()进行分组,否则(即一个()分组都没),在存在满足正则表达式的情况下使用groups返回的很有可能是一个空的元组

import re

regex = re.compile(r'\d+')
str1 = 'abcd78dfg9sdf0'

# search 的使用
result = regex.search(str1)

print(result.groups()) # ()
print(result.group(1)) #  IndexError: no such group

re.findall

findall(string[, pos[, endpos]])方法是查找这个字符串符合正则表达式的所有结果并放到一个列表中,返回一个列表,而不是成功匹配一个就结束,全部匹配不成功就返回空列表[]。

import re

regex = re.compile(r'\d+')
str1 = '66abcd78dfg9sdf0'

# findall 的使用
result = regex.findall(str1)
print(result) # ['66', '78', '9', '0']

re.finditer

finditer 方法的行为跟 findall 的行为类似,也是搜索整个字符串,获得所有匹配的结果。但它返回一个顺序访问每一个匹配结果(Match 对象)的迭代器。

import re

regex = re.compile(r'\d+')
str1 = '66abcd78dfg9sdf0'

# finditer 的使用
result = regex.finditer(str1)
print(type(result)) # <class 'callable_iterator'>

for item in result: # item 是Match 对象
    print(item.group())
#66
#78
#9
#0

re.split

split(string[, maxsplit])按照匹配到的子符串将原字符串分割后返回到一个列表,maxsplit 用于指定最大分割次数,不指定将全部分割。

import re

regex = re.compile(r'[\s;,:]+')
str1 = 'a;b,c:d   e f'

print(regex.split(str1))
# ['a', 'b', 'c', 'd', 'e', 'f']

re.sub

sub(repl, string[, count])方法用于替换。
其中,repl 可以是字符串也可以是一个函数,count 用于指定最多替换次数,不指定时全部替换即会像findall那样匹配整个字符串。

  • 如果 repl 是字符串,则会使用 repl 去替换字符串每一个匹配的子串,并返回替换后的字符串,另外,repl 还可以使用 id 的形式来引用分组,但不能使用编号 0;

import re

regex = re.compile(r'(\w+) (\w+)')
str1 = 'hello 123, hello 456'

print (regex.sub(r'hello world', str1))
# hello world, hello world

print (regex.sub(r'\2 \1', str1))
# 123 hello, 456 hello
  • 如果 repl 是函数,这个方法应当只接受一个参数(Match 对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。

import re
regex = re.compile(r'(\w+) (\w+)')
str1 = 'hello 123, hello 456'
def func(m):
    print(m)
    # <_sre.SRE_Match object; span=(0, 9), match='hello 123'>;<_sre.SRE_Match object; span=(11, 20), match='hello 456'>
    print(m.group(1)) # hello; hello
    print(m.group(2)) # 123;   456
    return 'hi' + ' ' + m.group(2)  # hi 123 ; hi 456

print (regex.sub(func, str1))
# hi 123, hi 456

贪婪与非贪婪

贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配 ( * );
非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配 ( ? );
Python里数量词默认是贪婪的。

import re

str1 = '<div>abcd</div><div>efgh</div>'
regex_greed = re.compile(r'<div>.*</div>')
regex_not_greed = re.compile(r'<div>.*?</div>')

result_greed = regex_greed.findall(str1)
result_not_greed = regex_not_greed.findall(str1)

print(result_greed)
# ['<div>abcd</div><div>efgh</div>']

print(result_not_greed)
# ['<div>abcd</div>', '<div>efgh</div>']

匹配中文

中文的 unicode 编码范围 主要在 [u4e00-u9fa5]

import re

str1 = '你好世界,hello world'
pattern = re.compile(r'[\u4e00-\u9fa5]+')
result = pattern.findall(str1)

print (result) # 你好世界

特殊构造?:的用法

当?:出现在正则表达式时,虽然正则表达式中使用()但这时()已经失去分组的特殊功能,表示(?:…)不分组版本,后面可以接|或这数量词,看例子:

?:结合|的使用

我们想获取所有abc或者efg的字符串,当没有使用?:的情况:

import re

regex = re.compile(r'(abc)|(efg)')
str1 = 'abchhggefg'
result = regex.findall(str1)

print(result)  # [('abc', ''), ('', 'efg')]

我们想获取所有abc或者efg的字符串,使用了?:之后,符合我们的预期:

import re

regex = re.compile(r'(?:abc)|(?:efg)')
str1 = 'abchhggefg'
result = regex.findall(str1)

print(result)  # ['abc', 'efg']

?:结合数量词{m}的使用

我们想匹配abc连续出现2次的字符串

  • 没结合?:的输出结果

import re

str1 = 'edabcabcefg'
regex = re.compile(r'(abc){2}')
result = regex.findall(str1)

print(result)  # ['abc']
  • 结合?:的输出结果,符合预期

import re

str1 = 'edabcabcefg'
regex = re.compile(r'(?:abc){2}')
result = regex.findall(str1)

print(result)  # ['abcabc']


以上是关于正则表达式常用规则与应用的主要内容,如果未能解决你的问题,请参考以下文章

常用正则表达式最强汇总(含Python代码举例讲解+爬虫实战)

常用正则表达式—想说爱你不容易

Java基础学习笔记十三 常用API之正则表达式DateDateFormatCalendar

编程中常用的正则表达式大全(上)

常见正则表达式及身份证校验规则

JDK中的API类库---正则表达式的应用