python正则表达式

2019-07-27  本文已影响0人  枫頔

正则表达式(regular expression),是匹配文本字段的模式。其设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。若想使用正则表达式处理字符串,必须使用支持正则表达式的工具。python提供了对正则表达式的支持。

下图展示了适用于python的正则表达式元字符及说明:

img

python提供re模块实现对正则表达式的支持。

1. re模块函数

1.1 match()函数

格式:re.match(pattern, string, flags=0)

match对象支持以下方法:

# 正则表达式:re.match()
import re

str1 = "one2two33four"
str2 = "12345..7890"

# 正则表达式:匹配两边若干个数字,中间若干个.组成的字符串
pattern = r"(\d+)\.*(\d+)"

# 返回匹配对象
result1 = re.match(pattern, str1
result2 = re.match(pattern, str2)


print(result1)  # 未匹配到返回None
print(result2)  # 匹配到返回match对象

print(result2.group())  # 返回正则表达式匹配到的结果
print(result2.group(0))  # 返回正则表达式匹配到的结果
print(result2.group(1, 2))  # 返回正则表达式中两个分组匹配到的结果(元组)
print(result2.group(1))  # 返回正则表达式中第一个分组匹配到的结果
print(result2.group(2))  # 返回正则表达式中第二个分组匹配到的结果
print(result2.groups())  # 返回正则表达式中每个分组匹配到的结果(元组)
                   
# 执行结果
None
<re.Match object; span=(0, 11), match='12345..7890'>
12345..7890
12345..7890
('12345', '7890')
12345
7890
('12345', '7890')              
1.2 search()函数

格式:re.search(pattern, string, flags=0)

# 正则表达式:re.search()
import re

str1 = "one123...456seven789...345"

# 正则表达式:匹配匹配两边若干个数字,中间若干个.组成的字符串
pattern = r"(\d+)\.*(\d+)"

result = re.search(pattern, str1)
print(result)

print(result.group())
print(result.group(0))
print(result.group(1, 2)) 
print(result.group(1)) 
print(result.group(2)) 
print(result.groups()) 

# 执行结果
<re.Match object; span=(3, 12), match='123...456'>
123...456
123...456
('123', '456')
123
456
('123', '456')
1.3 findall()函数

格式:re.findall(pattern, string, flags=0)

# 正则表达式:re.findall()

import re

str1 = "123four567eight"
str2 = "one123...456seven789...345"


# 正则表达式
pattern1 = r"\d+"
pattern2 = r"(\d+)\.*(\d+)"

result1 = re.findall(pattern1, str1)
result2 = re.findall(pattern2, str2)
print(result1)
print(result2)

# 执行结果
['123', '567']
[('123', '456'), ('789', '345')]
1.4 sub()函数

格式:re.sub(pattern, repl, string, count=0, flags=0)

# 正则表达式:re.sub()
import re

def deal(matchobj):
    # 根据匹配结果的长度返回不同的替换字符串
    if len(matchobj.group()) <= 6:
        return "---------"
    else:
        return "*********"


str1 = "one12..56seven789...345"

# 正则表达式:此处会匹配到两个结果会对两个结果进行替换
pattern = r"(\d+)\.*(\d+)"

result1 = re.sub(pattern, "_replace_string_", str1)  # 使用字符串替换
result2 = re.sub(pattern, deal, str1)  # 使用函数处理替换
result3 = re.sub(pattern, r"\2 \1", str1)

print(result1)
print(result2)
print(result3)

# 执行结果
one_replace_string_seven_replace_string_
one---------seven*********
one56 12seven345 789
1.5 subn()函数

格式:re.subn(pattern, repl, string, count=0, flags=0)

import re

result01 = re.subn(r'(\w+) (\w+)', r'hello world', 'hello 123, hello 456')
result02 = re.subn(r'(\w+) (\w+)', r'\2 \1', 'hello 123, hello 456')

print(result01)
print(result02)
# 结果
('hello world, hello world', 2)
('123 hello, 456 hello', 2)
1.6 split()函数

格式:re.split(pattern, string, maxsplit=0, flags=0)

# 正则表达式:re.split()
import re

str1 = "info:xiaoZhang 33 shandong"

pattern = r":| "

result = re.split(pattern, str1)
print(result)

# 执行结果
['info', 'xiaoZhang', '33', 'shandong']

2. 正则表达式对象的方法

可使用re.compile()函数将正则表达式编译为哟个正则表达式对象,然后使用对象的方法实现字符串匹配。

2.1 compile()函数

该函数用于编译正则表达式,形式如:re.compile(pattern, flags=0)。返回一个pattern对象。

2.2 match()方法

格式:pattern.match(string: AnyStr, pos: int = ..., endpos: int = ...)

# match()方法
import re

str1 = "12345..7890"
str2 = "zjbiafbia456....89764"

pattern = re.compile(r"(\d+)\.*(\d+)")
print(pattern)

result1 = pattern.match(str1)
result2 = pattern.match(str2, 9, 21)  # 制定匹配的范围
print(result1)
print(result2)

print(result1.start())  # 打印匹配结果的开始索引
print(result1.end())  # 打印匹配结果的结束索引
print(result1.group())  # 打印匹配的结果
print(result1.group(0))  # 打印匹配的结果
print(result1.group(1))  # 打印打印匹配结果中的第一个分组结果
print(result1.group(2))  # 打印打印匹配结果中的第二个分组结果

print(result2.group())
print(result2.group(0))
print(result2.group(1))
print(result2.group(2))

# 执行结果
re.compile('(\\d+)\\.*(\\d+)')
<re.Match object; span=(0, 11), match='12345..7890'>
<re.Match object; span=(9, 21), match='456....89764'>
0
11
12345..7890
12345..7890
12345
7890
456....89764
456....89764
456
89764
2.3 search()方法

格式:Pattern.search(string[, pos[, endpos]])

# search()方法
import re

str1 = "one123...456seven789...345"

# 正则表达式:匹配匹配两边若干个数字,中间若干个.组成的字符串
pattern = re.compile(r"(\d+)\.*(\d+)")

result = pattern.search(str1)
print(result)

print(result.start())  # 返回匹配字符串的开始索引
print(result.end())  # 返回匹配字符串的结束索引
print(result.group())  # 返回正则表达式匹配到的结果
print(result.group(0))  # 返回正则表达式匹配到的结果
print(result.group(1, 2))  # 返回正则表达式中两个分组匹配到的结果(元组)
print(result.group(1))  # 返回正则表达式中第一个分组匹配到的结果
print(result.group(2))  # 返回正则表达式中第二个分组匹配到的结果
print(result.groups())  # 返回正则表达式中每个分组匹配到的结果(元组)

# 执行结果
<re.Match object; span=(3, 12), match='123...456'>
3
12
123...456
123...456
('123', '456')
123
456
('123', '456')
2.4 findall()方法

格式:Pattern.findall(string[, pos[, endpos]])

# findall()方法
import re

str1 = "123four567eight"
str2 = "one123...456seven789...345"


# 正则表达式
pattern1 = re.compile(r"\d+")
pattern2 = re.compile(r"(\d+)\.*(\d+)")

result1 = pattern1.findall(str1)
result2 = pattern2.findall(str2)
print(result1)
print(result2)

# 执行结果
['123', '567']
[('123', '456'), ('789', '345')]
2.5 split()方法

格式:Pattern.split(string, maxsplit=0) 类似于re.split()方法,分割字符串。

# split()方法
import re

str1 = "info:xiaoZhang 33 shandong"

pattern = re.compile(r":| ")

result = pattern.split(str1)
print(result)

# 执行结果
['info', 'xiaoZhang', '33', 'shandong']
2.6 sub()方法
# sub()方法
import re

def deal(matchobj):
    # 根据匹配结果的长度返回不同的替换字符串
    if len(matchobj.group()) <= 6:
        return "---------"
    else:
        return "*********"


str1 = "one12..56seven789...345"

# 正则表达式:此处会匹配到两个结果会对两个结果进行替换
pattern = re.compile(r"(\d+)\.*(\d+)")

result1 = pattern.sub("_replace_string_", str1)  # 使用字符串替换
result2 = pattern.sub(deal, str1)  # 使用函数处理替换
result3 = pattern.sub(r"\2 \1", str1)

print(result1)
print(result2)
print(result3)

# 执行结果
one_replace_string_seven_replace_string_
one---------seven*********
one56 12seven345 789

subn()

使用字符串或函数返回的字符串替换pattern对象匹配到的字符串,返回一个元组(替换后的字符串, 替换的次数),等同于re.subn()函数。

import re

pattern = re.compile(r'(\w+) (\w+)')
word = 'hello 123, hello 456'

def func(word):
    return 'hi' + ' ' + word.group(1)  # 返回一个字符串用于替换

print(pattern.subn(r'hello world', word))  # 使用字符串替换
print(pattern.subn(r'\2 \1', word))  # 引用匹配到的子串的分组进行替换
print(pattern.subn(func, word))  # 使用函数返回一个字符串用于替换
print(pattern.subn(func, word, 1))   # 指定替换的次数
# 结果
('hello world, hello world', 2)
('123 hello, 456 hello', 2)
('hi hello, hi hello', 2)
('hi hello, hello 456', 1)

从上面可以看出re模块有两种使用方式:

如何选择使用方式呢?如果一个正则表达式需要使用多次,出于效率的考虑,可预编译正则表达式,即第二种方式。

3. 匹配中文

中文的 unicode 编码范围 主要在 [\u4e00-\u9fa5],这里说主要是因为这个范围并不完整,比如没有包括全角(中文)标点,不过,在大部分情况下,应该是够用的。

import re

word = '你好,hello,世界'

result = re.findall(r'[\u4e00-\u9fa5]+', word)
print(result)
# 结果
['你好', '世界']

4. 贪婪匹配

python中,正则表达式默认为贪婪匹配,即匹配尽可能多的字符。

import re

word = 'aa<div>test1</div>bb<div>test2</div>cc'

result = re.findall(r'<div>.+</div>', word)
print(result)

result = re.findall(r'<div>.+?</div>', word)
print(result)
# 结果
['<div>test1</div>bb<div>test2</div>']
['<div>test1</div>', '<div>test2</div>']

由于是贪婪匹配,在成功匹配第一个</div>后,会继续向右尝试匹配,查看是否还有更长的可以成功匹配的子串。若想非贪婪匹配,可在+后面添加一个?。

上一篇 下一篇

猜你喜欢

热点阅读