Python中的正则表达式

re模块

re是提供正则表达式匹配操作的模块.

在任何编程语言中, 对文本字符串的处理都是一个比较重要的内容.

前面我们已经学习过str, 但是他对正则表达式的处理能力相对比较弱, 目前各大编程语言都支持一种更强的处理字符串的工具:正则表达式(regular expression)

字符串是在程序处理的最多的一种数据, 程序对字符串的操作简直无处不在.

比如去判断用户的输入的数据是否为一个合法的电话号码, 如果像以前的普通的处理方式, 一个一个的字符去判断就非常的麻烦, 代码的可读性也差. 判断一个 email 是不是一个合法的电邮等等这些需求, 都是比较平常的问题.

所以, 各大编程语言几乎都支持一种功能更加强大, 简单易用的处理字符串的工具: 正则表达式

一、什么是正则表达式

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。

Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。

re 模块使 Python 语言拥有全部的正则表达式功能。

re 模块提供了一些方法,这些方法使用一个模式字符串做为它们的第一个参数。

二、正则表达式的基本使用

正则表达式用的最多的两个函数是re.match()re.search()


2.1 使用re.match()

match()视图从字符串的起始位置对模式进行匹配.

如果匹配成功, 就返回一个匹配对象, 如果匹配失败, 就返回 None.

匹配对象的group()方法能够显示那个成功的匹配.

使用语法:

re.match(pattern, string[, flags=0])

参数说明:

  1. 匹配的正则表达式. 直接传入一个字符串, python 会把这个字符串作为正则表达式来对待
  2. 要匹配的字符串.
  3. 标志位:用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
import re

m = re.match("foo", "foo_my")
print(m.group())

注意:

match()匹配是从字符串的开始位置匹配, 如果开始不匹配则不会匹配成功, 返回一个 None

import re

m = re.match("foo", "afoo_my")
print(m)    # 匹配不成功, 返回 None. 

2.2 使用re.search()

re.match()总是从字符串的开始位置开始匹配, 所以很多情况下能够匹配的概率不大.

re.search()是在字符串中搜索正则表达式模式, 任何位置都可以. 返回的是第一次出现的匹配情况(因为正则字符串中可能会多处匹配)

他的参数和re.match()是一样的, 返回值也是一个匹配对象.

import re

m = re.search("foo", "afoo_my")    # 搜索成功
print(m.group())    # foo

2.3 re.match()和re.search()的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

三、正则表达式语法

正则表达式的强大之处是他提供了很多特殊符号和字符, 使用它们正则表达式就更加的强大和灵活.

这些特殊符号和字符我们称之为元字符.


表一:一般符号

符号描述
字面量匹配文本字符串的字面值
.匹配任意字符(除 \n 之外)
^匹配字符串的起始部分
$匹配字符串的终止部分
[abc]匹配a 或者 b 或者 c, 只匹配单一字符
[a-z]匹配 a 到 z 之间的任一字符
[0-9]匹配0-9之间的任一字符
[^abc]不匹配 abc 任一字符
[^a-z]不匹配 a-z 之间的任一字符

表二:特殊符号

特殊符号描述
\d匹配任何的十进制数字([0-9])
\D匹配非数字(与\d相反)
\w匹配数字字母下划线([a-zA-Z0-9_])
\W与\w相反
\b匹配任何单词边界
\B与\b 相反
\c匹配特殊字符. 比如: . 匹配. _ 匹配_ 其实就是使用\作为转义字符用而已.

表三:数量词

数量词描述
*匹配前面的0个或多个字符
?匹配0个或1个
+匹配1个或多个
{M}匹配正好 M 个, M是个数字
{M,}匹配至少 M 个
{M,N}匹配 M个-N个

择一匹配符号(|)

表示择一匹配的管道符(|), 表示一个"从多个模式中选择其一的操作". 它用于分割不公的正则表达式

at|home 匹配的字符串: at, home

r2de|c3po 匹配的字符串: r2de, c3pro

bat|bet|bit 匹配的字符串: bat, bet, bit

使用这个符号, 增强了正则表达式的灵活性. 择一匹配有的时候也称之为并(union)或者(logical OR)


分组()

使用()可以对正则表达式进行分组, 则在匹配对象中可以获取到匹配到的子组的字符串.


贪婪匹配模式

在用到数量词的匹配时, 默认的是贪婪模式.

贪婪模式的意思是说, 匹配的时候, 尽量多匹配, 不行在慢慢的减少匹配

import re

reg = "\d{2,4}"
result = re.match(reg, "12345abc")    # 贪婪模式, 尽量多的匹配, 所以能匹配 4 个数字
print(result.group())

懒惰匹配模式

懒惰匹配模式是正好和贪婪模式相对的一种模式.

懒惰匹配模式是尽量的少匹配, 不行再慢慢的去增加匹配的个数.

启用懒惰模式只需要在数量词的后面添加?即可.

import re

reg = "\d{2,4}?" # 懒惰模式, 会尽量的少匹配
result = re.match(reg, "12345abc") 
print(result.group())

四、标志位的说明

标志位对匹配过程做了一些限制.

标志位都是 re 模块内部已经预先定义好的常量

python3注意提供了以下几个标志位, 如果需要同时使用多个标志位, 使用 | 来实现.

标志位说明
re.A或 re.ASCII仅执行8位 ASCII 匹配 (python3开始支持)
re.I 或 re.IGNORECASE匹配的时候忽略大小写
re.M或re.MULTILINE^和KaTeX parse error: Can't use function '\(' in math mode at position 9: 执行多行匹配. \̲(̲对^和来说, 默认是只匹配字符串的开始和结尾)
re.S 或 re.DOTALL让点(.)匹配任意字符, 也包含换行符
re.X或re.VERBOSE忽略模式字符串中未转义的空格和注释
a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

五、匹配对象详解

匹配对象(Match Object)是我们使用re.match()re.search()匹配之后的返回值.里面封装了我们匹配的结果.

测试是否匹配

匹配对象总是可以当做true来用, 因为如果匹配不到对象, re.match()re.search()总是返回的是None.

所以, 我们可以使用下面简单的if语句, 来测试是否匹配.

match = re.search(pattern, string)
if match:
    process(match)

匹配对象的属性和方法

m.group([group1, group2..., ...])

返回匹配指定的一个或多个子分组.

参数就是分组编号.

如果只传递一个参数, 则返回匹配这个组的字符串, 如果传递多个参数则返回的是一个元组(tuple), 元组中存储的就是匹配的字符串.

如果传递的组号是无效, 则会抛出异常.

import re

# 正则表达式中一共分了两组 从前向后分别是第1组, 第2组. 整体是第 0 组
m = re.match("(\d+)([a-z]{2,5})", "1234abcd", re.I)
if m:
    print(m.group())  # 因为没有传递参数, 所以获取的是整个参数
    print(m.group(2))  # 只传递了一个参数, 所以获取的是一个字符串
    print(m.group(0, 1, 2))  # 传递多个参数, 获取到的是一个 tuple

m.groups(default=None)

返回一个元组, 包含了所有匹配的子组 (从第1组开始…).

参数是没有匹配字符的组返回字符串, 默认是 None

import re

# 正则表达式中一共分了两组 从前向后分别是第1组, 第2组. 整体是第 0 组
m = re.match(r"(\d+)\.(\d+)", "24.1632")
if m:
    print(m.groups())
    
m = re.match(r"(\d+)(\d+)?", "242222")
if m:
    print(m.groups())    # 获取不到的组是 None
    print(m.groups("abc"))    # 获取不到的组则用 abc 替换

m.start([group])m.end([group])

返回的指定组的匹配的字符串的开始位置(包括)和结束位置(不包括)

可以使用s[start:end]截取到匹配的字符串.

默认是0组, 表示整个正则表达式

import re

s = "24.1632"
m = re.match(r"(\d+)\.(\d+)", s)
if m:
    print(m.start(1))
    print(m.end(1))
    print(m.group(1))
    print(s[m.start(1):m.end(1)])

属性:m.lastIndex

指的是相匹配的最后一个组的索引(组号). 如果没有匹配的组, 则返回None

import re

s = "24.1632"
m = re.match(r"(\d+)\.(\d+)", s)
if m:
    print(m.groups())
    print(m.lastindex)   # 最后一个匹配的是第2组, 所以返回2

属性:m.string

传递给match()和 search()的字符串.

六、re模块的其他函数

re模块中除了常用的两个函数re.match()re.search()外, 还有一些其他经常用到的函数.

拆分字符串:re.split(pattern, string)

根据指定的模式去切割字符串, 返回的是是一个列表, 包含了切割到的所有字符串.

import re

s = "10.20.3.220"
r = re.split("\.", s)
print(r)

替换字符串1:re.sub(pattern, repl, string)

repl去替换满足模式的子字符串.

返回值就是替换后的新的字符串.

import re

s = "abc1234flll67a89"
r = re.sub("\d+", "X", s)
print(r)

替换字符串2:re.subn(pattern, repl, string)

re.sub()是一样的, 但是返回值是一个元组, 包含新字符串和替换的次数.

import re

s = "abc1234flll67a89"
r = re.subn("\d+", "X", s)
print(r)

找到所有匹配1: re.findall(pattern, string)

在字符串找到所有的匹配子字符串.

如果有分组, 则返回与分组匹配的字符串.

如果使用了不止一个分组, 返回的列表中, 每一项都是一个元组

import re

s = "abc1234fa67a89"
r = re.findall("\d+[a-z]+", s)
print(r)
r = re.findall("(\d+)[a-z]+", s)
print(r)
r = re.findall("(\d+)([a-z]+)", s)
print(r)

找到所有的匹配2: re.finditer(pattern, string)

re.findall是一样的, 只是re.finditer()返回的是一个迭代器.

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值