match() 和 search() 的不同
import re
# 注意:要从字符串的起始位置开始匹配
m = re.match("foo","my foo on the table")
if m is not None:
print(m.group())
else:
print("没有找到匹配的元素")
控制台打印:没有找到匹配的元素
import re
# 搜索的模式出现在一个字符串中间
m = re.search('foo','my foo on the table')
if m is not None:
print(m.group())
else:
print("没有找到匹配的元素")
控制台打印:foo
import re
m = re.search('foo', 'seafood')
if m is not None: print(m.group())
控制台打印:foo
方法 match()import re
bt = 'bat|bet|bit'
m = re.match(bt,'bat')
if m is not None:
print(m.group())
控制台打印:bat。
说明:在没有括号的情况下,使用 m.group()
得到返回。
方法 search()
import re
haRegex = re.compile('(Ha){3,5}')
mo1 = haRegex.search('bbbHaHaHaHaHabbb')
print(mo1.group())
# 不加问号,是贪心模式,匹配最多
# HaHaHaHaHa
haRegex = re.compile('(Ha){3,5}?')
mo1 = haRegex.search('bbbHaHaHaHaHabbb')
print(mo1.group())
# 还可以在花括号后面加上问号,表示非贪心的匹配
# HaHaHa
分隔符不一致的情况下,可以使用 re.split() 的方法。虽然字符串对象也提供了 split() 方法。
import re
line = 'asdf fjdk; afed, fjek,asdf, foo'
list = re.split(r'[;,\s]\s*', line)
print(list)
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
贪婪模式与非贪婪模式:
比较下面的两个例子:
.* 表示尽可能多地去匹配
import re
a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx.*xx', a)
print(b)
# 控制台打印:['xxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxx']
.*? 表示尽可能少地匹配
import re
a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx.*?xx', a)
print(b)
# 控制台打印:['xxIxx', 'xxlovexx', 'xxUxx']
这里写代码片
方法 findall
import re
relink = '<a href="(.*)">(.*)</a>'
info = '<a href="http://www.baidu.com">baidu</a>'
cinfo = re.findall(relink, info)
print(type(cinfo)) # <class 'list'>
print(cinfo[0]) # ('http://www.baidu.com', 'baidu')
print(cinfo[0][0]) # http://www.baidu.com
print(cinfo[0][1]) # baidu
import re
info = "abcd efg hij klmn"
# 不带有括号,其输出的内容就是整个表达式所匹配到的内容
regex1 = re.compile("\w+\s+\w+")
list1 = regex1.findall(info)
print(list1)
# 带有 1 个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。
regex2 = re.compile("(\w+)\s+\w+")
list2 = regex2.findall(info)
print(list2)
# 带有 3 个括号,我们可以看到其输出是一个 list 中包含 3 个 tuple
regex3 = re.compile("((\w+)\s+(\w+))")
list3 = regex3.findall(info)
print(list3)
结论:findall()
返回的是括号所匹配到的结果,多个括号就会返回多个括号分别匹配到的结果,如果没有括号就返回就返回整条语句所匹配到的结果。所以在提取数据的时候就需要注意这个坑。
如果一个正则表达式有分组,则 findall 方法返回 tuple 的列表。
findall_group_regex = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo2 = findall_group_regex.findall('1987-07-06,1990-03-30,1987-03-20')
print(mo2)
# [('1987', '07', '06'), ('1990', '03', '30'), ('1987', '03', '20')]
findall() 找到所有匹配的方法,返回一组字符串(即字符串列表),包含被查找字符串中的所有匹配。
问号实现可选的匹配。
注意:问号在正则表达式中可能有两种含义:
1、声明非贪心的匹配
2、表示可选的分组
用星号匹配零次或者多次。
用加号匹配一次或者多次。
用花括号匹配特定的次数。
贪心和非贪心的匹配。
Python 的正则表达式默认是贪心的。这表示,在有“二义”的情况下,它们会尽可能地匹配最长的字符串。
在花括号的后面加上一个问号,即表示花括号的“非贪心”版本。
第 1 个参数是正则表达式
import re
a='xyz123'
# . 匹配任意一个字符
b = re.findall('x..',a)
print(b)
[‘xyz’]
例:
import re
a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx(.*?)xx', a)
print(b)
print(type(b))
for item in b:
print(item)
控制台打印:
['I', 'love', 'U']
<class 'list'>
I
love
U
re.S
re.S 的作用是让 . 的作用包含了换行符 \n,这一点我们可以通过看 Python3 的源码得知。
例:
请比较有 re.S
和没有 re.S
参数的不同:
import re
a = """rewixxhello
aaaaaaaxxuirwifdsfsdxxworldxxfkjsjke"""
b = re.findall("xx(.*?)xx", a, re.S)
print(b)
控制台打印:
['hello\naaaaaaa', 'world']
findall()
函数里面本身就有 compile()
方法。所以不用多此一举,先编译一下再使用。
使用 \d+
表示纯数字。
Regex 的 search() 方法查找传入的字符串对象。
在 Python 中使用正则表达式的步骤:
1、import re
2、re.compile()
3、向 Regex 对象的 search() 方法中传入想查找的字符串,它返回一个 Match 对象。
4、调用 Match 对象的 group() 方法,返回实际匹配文本的字符串。
import re
phone_num_rex = re.compile(r'\d{3}-\d{4}-\d{4}')
mo = phone_num_rex.search('My Numver is 137-3062-9072')
print('Phone number found:' + mo.group())
print(type(mo.group()))
控制台打印:
Phone number found:137-3062-9072
<class 'str'>
说明:“\n” 表示一个换行符。
下面解释一下 re.compile(r'\d{3}-\d{4}-\d{4}')
的前面为什么要加上一个“r”。
通过在字符串的第一个引号之前加上 r ,可以将该字符串标记为原始字符串,它不包括转义字符。
正则表达式的分组
import re
# 分组得到的每一个元素是元组 tuple
findall_group_regex = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo2 = findall_group_regex.findall('1987-07-06,1990-03-30,1987-03-20')
print(type(mo2))
for item in mo2:
print(type(item))
控制台显示:
<class 'list'>
('1987', '07', '06')
('1990', '03', '30')
('1987', '03', '20')
利用括号分组
1、第 1 对括号就是第 1 组
2、向 group() 匹配对象方法传入整数 1 或者 2,就可以取得匹配文本的不同部分;
3、向 group() 匹配对象方法传入整数 0 或者 不传,就可以取得匹配文本的全部。
一次获取所有的分组,使用 groups() 方法,返回的是元组,所以,我们可以使用多重赋值的技巧。
元组还可以这样赋值:
a, b, c = (1, 2, 3)
print(a)
print(b)
print(c)
示例:
import re
dateStr = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo = dateStr.search('1987-07-06')
# 是一个元组
print(type(mo.groups()))
year, month, day = mo.groups()
print(year)
print(month)
print(day)
字符的分类
\d: 0 到 9 的任何数字
\D: 除了 0 到 9 的数字以外的任何字符
\w: 任何字母、数字或者下划线字符(可以认为是匹配“单词”字符)
\W:
\s: 空格、制表符或者换行符(可以认为是匹配“空白”字符)
\S:
用 sub() 方法替换字符串。