Python 正则表达式学习笔记

来源:互联网 发布:公司如何做网络推广 编辑:程序博客网 时间:2024/06/05 02:52

  • 方法 match
    • 方法 search
    • 贪婪模式与非贪婪模式
    • 方法 findall
    • 问号实现可选的匹配
    • reS
    • 正则表达式的分组

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 rem = re.search('foo', 'seafood')if m is not None: print(m.group())

控制台打印:foo

方法 match()

import rebt = 'bat|bet|bit'm = re.match(bt,'bat')if m is not None:    print(m.group())

控制台打印:bat。
说明:在没有括号的情况下,使用 m.group() 得到返回。

import rehaRegex = re.compile('(Ha){3,5}')mo1 = haRegex.search('bbbHaHaHaHaHabbb')print(mo1.group())# 不加问号,是贪心模式,匹配最多# HaHaHaHaHahaRegex = re.compile('(Ha){3,5}?')mo1 = haRegex.search('bbbHaHaHaHaHabbb')print(mo1.group())# 还可以在花括号后面加上问号,表示非贪心的匹配# HaHaHa

分隔符不一致的情况下,可以使用 re.split() 的方法。虽然字符串对象也提供了 split() 方法。

import reline = 'asdf fjdk; afed, fjek,asdf,  foo'list = re.split(r'[;,\s]\s*', line)print(list)# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

贪婪模式与非贪婪模式:

比较下面的两个例子:

.* 表示尽可能多地去匹配

import rea = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'b = re.findall('xx.*xx', a)print(b)# 控制台打印:['xxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxx']

.*? 表示尽可能少地匹配

import rea = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'b = re.findall('xx.*?xx', a)print(b)# 控制台打印:['xxIxx', 'xxlovexx', 'xxUxx']

这里写代码片

方法 findall

import rerelink = '<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.comprint(cinfo[0][1]) # baidu

import reinfo = "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 个 tupleregex3 = 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 rea='xyz123'# . 匹配任意一个字符b = re.findall('x..',a) print(b)

[‘xyz’]

例:

import rea = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'b = re.findall('xx(.*?)xx', a)print(b)print(type(b))for item in b:    print(item)

控制台打印:

['I', 'love', 'U']<class 'list'>IloveU

re.S

re.S 的作用是让 . 的作用包含了换行符 \n,这一点我们可以通过看 Python3 的源码得知

例:
请比较有 re.S 和没有 re.S 参数的不同:

import rea = """rewixxhelloaaaaaaaxxuirwifdsfsdxxworldxxfkjsjke"""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 rephone_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# 分组得到的每一个元素是元组 tuplefindall_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 redateStr = 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() 方法替换字符串。

原创粉丝点击