正则表达式(Regular Expression)是字符串处理的常用工具,通常被用来检索、替换那些符合某个模式(Pattern)的文本。很多程序设计语言都支持正则表达式,像Perl、Java、C/C++。在 Python 中是通过标准库中的re 模块 提供对正则的支持。

一、正则表达式介绍

在使用 re 模块之前,先来了解一下正则表达式的基本语法。

1)用途

通过使用正则表达式,可以:

  • 测试字符串内的模式。—— 例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。

  • 替换文本。—— 可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

  • 基于模式匹配从字符串中提取子字符串。—— 可以查找文档内或输入域内特定的文本。

2)语法

本文主要介绍正则的基本语法以及 re 模块的使用,不包括如何编写高效的正则表达式、如何优化正则表达式,这些主题请看其他教程。

下图列出了Python支持的一些正则表达式元字符和语法:

3)贪婪模式与非贪婪模式

“贪婪模式”总是尝试匹配尽可能多的字符;“非贪婪模式”则相反,总是匹配尽可能少的字符。例如,用"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。

二、使用 re 模块

下面我们开始来使用 re 模块。

1)编译正则表达式

re 模块提供了 re.compile() 函数将一个字符串编译成 pattern object,用于匹配或搜索。函数原型如下:

re.compile(pattern, flags=0)

re.compile() 还接受一个可选的参数 flag,用于指定正则匹配的模式。关于匹配模式,后面将会讲到。

p = re.compile('ab*', re.IGNORECASE)

2)反斜杠的困扰

在 python 的字符串中,\ 是被当做转义字符的。在正则表达式中,\ 也是被当做转义字符。这就导致了一个问题:如果你要匹配 \ 字符串,那么传递给 re.compile() 的字符串必须是"\\\\"。

由于字符串的转义,所以实际传递给 re.compile() 的是"\\",然后再通过正则表达式的转义,"\\" 会匹配到字符"\"。这样虽然可以正确匹配到字符 \,但是很麻烦,而且容易漏写反斜杠而导致 Bug。那么有什么好的解决方案呢?

原始字符串很好的解决了这个问题,通过在字符串前面添加一个r,表示原始字符串,不让字符串的反斜杠发生转义。那么就可以使用r"\\"来匹配字符\了。

3)pattern object 执行匹配

一旦你编译得到了一个 pattern object,你就可以使用 pattern object 的方法或属性进行匹配了,下面列举几个常用的方法,更多请看这里

regex.match(string[, pos[, endpos]])

  • 匹配从 pos 到 endpos 的字符子串的开头。匹配成功返回一个 match object,不匹配返回 None。
  • pos 的默认值是0,endpos 的默认值是 len(string),所以默认情况下是匹配整个字符串的开头。
import re
pattern = re.compile("ar{1}")
print(pattern.match("army")) # "ar"在开头,匹配成功
print(pattern.match("mary")) # "ar"不在开头,匹配失败
print(pattern.match("mary", 1)) # "ar"不在开头,但在子串的开头 # 输出结果:
# <_sre.SRE_Match object; span=(0, 2), match='ar'>
# None
# <_sre.SRE_Match object; span=(1, 3), match='ar'>

regex.search(string[, pos[, endpos]])

  • 扫描整个字符串,并返回它找到的第一个匹配(Match object)。
  • 和 regex.match() 一样,可以通过 pos 和 endpos 指定范围。
pattern = re.compile("ar{1}")
match = pattern.search("mary") # search
print(match) # 输出结果:
# <_sre.SRE_Match object; span=(1, 3), match='ar'>

regex.findall(string[, pos[, endpos]])

  • 找到所有匹配的子串,并返回一个 list 。
  • 可选参数 pos 和 endpos 和上面一样。
pattern = re.compile(r"\d+")
lst = pattern.findall("abc1def2rst3xyz") # findall
print(lst) # 输出结果:
# ['1', '2', '3']

regex.finditer(string[, pos[, endpos]])

  • 找到所有匹配的子串,并返回由这些匹配结果(match object)组成的迭代器。
  • 可选参数 pos 和 endpos 和上面一样。
pattern = re.compile(r"\d+")
p = pattern.finditer("abc1def2rst3xyz")
for i in p:
print(i) # 输出结果:
# <_sre.SRE_Match object; span=(3, 4), match='1'>
# <_sre.SRE_Match object; span=(7, 8), match='2'>
# <_sre.SRE_Match object; span=(11, 12), match='3'>

4)match object 获取结果

在上面讲到,通过 pattern object 的方法(除 findall 外)进行匹配得到的返回结果都是
match object。每一个 match object 都包含了匹配到的相关信息,比如,起始位置、匹配到的子串。那么,我们如何从 match object 中提取这些信息呢?

match object 提供了一些方法,下面列举几个常用的方法,更多请看这里

match.group([group1, ...])

  • 返回 match object 中的字符串。
  • 每一个 ( ) 都是一个分组,分组编号从1开始,从左往右,每遇到一个左括号,分组编号+1。
  • 组 0 总是存在的,它就是整个表达式 。
  • 没有参数时,group1默认为0,这时返回整个匹配到的字符串。
  • 指定一个参数(整数)时,返回该分组匹配到的字符串。
  • 指定多个参数时,返回由那几个分组匹配到的字符串组成的 tuple。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m) # <_sre.SRE_Match object; span=(0, 11), match='Kobe Bryant'>
print(m.group()) # Kobe Bryant
print(m.group(1)) # Kobe
print(m.group(2)) # Bryant
print(m.group(1, 2)) # ('Kobe', 'Bryant')

match.groups()

  • 返回由所有分组匹配到的字符串组成的 tuple。
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')

match.start([group])

  • 没有参数时,返回匹配到的字符串的起始位置。
  • 指定参数(整数)时,返回该分组匹配到的字符串的起始位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.start()) # 0
print(m.start(2)) # 5

match.end([group])

  • 没有参数时,返回匹配到的字符串的结束位置。
  • 指定参数(整数)时,返回该分组匹配到的字符串的结束位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.end()) # 11
print(m.end(1)) # 4

match.span([group])

  • 返回一个二元 tuple 表示匹配到的字符串的范围,即 (start, end)。
  • 指定参数时,返回该分组匹配到的字符串的 (start, end)。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.span()) # (0, 11)
print(m.span(2)) # (5, 11)

5)模块级别的函数

上面讲到的函数都是对象的方法,要使用它们必须先得到相应的对象。本节将介绍一些Module-Level Functions,比如 match(),search(),findall() 等等。你不需要创建一个 pattern object 就可以直接调用这些函数。

re.compile(pattern, flags=0):上面已经介绍过。

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

pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
# 相当于
m = re.match(r"(\w+) (\w+)","Kobe Bryant, Lakers")

re.search(pattern, string, flags=0)

pattern = re.compile(r"(\w+) (\w+)")
m = pattern.search("Kobe Bryant, Lakers")
# 相当于
m = re.search(r"(\w+) (\w+)","Kobe Bryant, Lakers")

re.findall(pattern, string, flags=0):与上面类似。

re.finditer(pattern, string, flags=0):与上面类似。

6)编译标志(匹配模式)

在讲 re.compile() 函数时,曾说到该函数还接受可选的第二个参数,用以设置匹配模式。可选的匹配模式有:

  • re.IGNORECASE:忽略大小写,同 re.I

  • re.MULTILINE:多行模式,改变^和$的行为,同 re.M

  • re.DOTALL:点任意匹配模式,让'.'可以匹配包括'\n'在内的任意字符,同 re.S

  • re.LOCALE:使预定字符类 \w \W \b \B \s \S 取决于当前区域设定, 同 re.L

  • re.ASCII:使 \w \W \b \B \s \S 只匹配 ASCII 字符,而不是 Unicode 字符,同
    re.A

  • re.VERBOSE:详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。主要是为了让正则表达式更易读,同re.X。例如,以下两个正则表达式是等价的:

a = re.compile(r"""\d +  # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

三、修改字符串

第二部分讲的是字符串的匹配和搜索,但是并没有改变字符串。下面就讲一下可以改变字符串的操作。

1)分割字符串

split()函数在匹配的地方将字符串分割,并返回一个 list。同样的,re 模块提供了两种 split 函数,一个是 pattern object 的方法,一个是模块级的函数。

regex.split(string, maxsplit=0)

  • maxsplit用于指定最大分割次数,不指定将全部分割。
pattern = re.compile(r"[A-Z]+")
m = pattern.split("abcDefgHijkLmnoPqrs")
print(m) # 输出结果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']

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

  • 模块级函数,功能与 regex.split() 相同。
  • flags用于指定匹配模式。
m = re.split(r"[A-Z]+","abcDefgHijkLmnoPqrs")
print(m) # 输出结果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']

2)搜索与替换

另一个常用的功能是找到所有的匹配,并把它们用不同的字符串替换。re 模块提供了sub()subn()来实现替换的功能,而它们也分别有自己两个不同版本的函数。

regex.sub(repl, string, count=0)

  • 使用 repl 替换 string 中每一个匹配的子串,返回替换后的字符串。若找不到匹配,则返回原字符串。
  • repl 可以是一个字符串,也可以是一个函数。
  • 当repl是一个字符串时,任何在其中的反斜杠都会被处理。
  • 当repl是一个函数时,这个函数应当只接受一个参数(Match对象),并返回一个字符串用于替换。
  • count 用于指定最多替换次数,不指定时全部替换。
def fun(m):
return m.group().upper() pattern = re.compile(r"like", re.I)
s1 = pattern.sub(r"love", "I like you, do you like me?")
s2 = pattern.sub(fun, "I like you, do you like me?")
print(s1)
print(s2) # 输出结果:
# I love you, do you love me?
# I LIKE you, do you LIKE me?

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

  • 模块级函数,与 regex.sub() 函数功能相同。
  • flags 用于指定匹配模式。

regex.subn(repl, string, count=0)

  • 同 sub(),只不过返回值是一个二元 tuple,即(sub函数返回值, 替换次数)

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

  • 模块级函数,功能同 regex.subn()。

Python3标准库(二) re模块的更多相关文章

  1. 7.Python3标准库--文件系统

    ''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...

  2. 8.Python3标准库--数据持久存储与交换

    ''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...

  3. Python3 标准库

    Python3标准库 更详尽:http://blog.csdn.net/jurbo/article/details/52334345 文本 string:通用字符串操作 re:正则表达式操作 diff ...

  4. python023 Python3 标准库概览

    Python3 标准库概览 操作系统接口 os模块提供了不少与操作系统相关联的函数. >>> import os >>> os.getcwd() # 返回当前的工作 ...

  5. python3标准库总结

    Python3标准库 操作系统接口 os模块提供了不少与操作系统相关联的函数. ? 1 2 3 4 5 6 >>> import os >>> os.getcwd( ...

  6. python常用标准库(时间模块 time和datetime)

    常用的标准库 time时间模块 import time time -- 获取本地时间戳 时间戳又被称之为是Unix时间戳,原本是在Unix系统中的计时工具. 它的含义是从1970年1月1日(UTC/G ...

  7. (转)python标准库中socket模块详解

    python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...

  8. 1.Python3标准库--前戏

    Python有一个很大的优势便是在于其拥有丰富的第三方库,可以解决很多很多问题.其实Python的标准库也是非常丰富的,今后我将介绍一下Python的标准库. 这个教程使用的书籍就叫做<Pyth ...

  9. 比较两个文件的异同Python3 标准库difflib 实现

    比较两个文件的异同Python3 标准库difflib 实现 对于要比较两个文件特别是配置文件的差异,这种需求很常见,如果用眼睛看,真是眼睛疼. 可以使用linux命令行工具diff a_file b ...

  10. python——模块、标准库、第三方模块安装

    模块(module)简介 模块化--指将一个完整的程序分解为一个一个小的模块,通过将模块组合,来搭建出一个完整的程序. 模块化的特点: ① 方便开发 ② 方便维护 ③ 模块可以复用! 在Python中 ...

随机推荐

  1. Method Dispatch in Protocol Extensions

    We learned in the Protocol-Oriented Programming session at WWDC 2015 that Swift uses two different d ...

  2. NLog小记

    NLog安装: Install-Package NLog NLog配置: <?xml version="1.0" encoding="utf-8" ?&g ...

  3. maven release插件将一版本发布到仓库中时Return code is: 401, ReasonPhrase:Unauthorized

    需要在maven的setting.xml中配置servers.server节点,其值为nexus的对应的repository的id以及用户名及密码 <servers> <server ...

  4. RabbitMQ 基础概念介绍

    AMQP 消息模型 RabbitMQ 是基于 AMQP(高级消息队列协议)的一个开源实现,其内部实际也是 AMQP 的基本概念.

  5. 【C语言】控制台窗口图形界面编程(一)句柄和文本属性

    目录 00. 目录 01. 句柄 02. GetStdHandle函数 03. CloseHandle函数 04. SetConsoleTextAttribute函数 05. 十进制颜色对照表 06. ...

  6. egg.js上传文件到本地

    'use strict'; const Service = require('egg').Service; const fs = require('fs'); const path = require ...

  7. [Algorithm] 1. A+B Problem

    Description Write a function that add two numbers A and B. Clarification Are a and b both 32-bit int ...

  8. Java设计模式之策略模式(Strategy Pattern)

    简介 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 组成 1.抽象策略角色(Strategy): 策略类,通常由一个接口或者抽象类实现. 2.具 ...

  9. Linux htop工具使用详解【转】

    原文地址: http://www.cnphp6.com/archives/65078 一.Htop的使用简介 大家可能对top监控软件比较熟悉,今天我为大家介绍另外一个监控软件Htop,姑且称之为to ...

  10. win7右键菜单不见解决办法

    直接 开始 运行: cmd /k reg add "HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers\Ne ...