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+ 表示纯数字。

Python 正则表达式学习笔记_元组

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() 方法替换字符串。