Python正则表达式急速入门(小结)

正则表达式在程序开发中会经常用到,比如数据(格式)验证、替换字符内容以及提取字符串内容等等情况都会用到,但是目前许多开发人员对于正则表达式只是处于了解或者是基本会用的阶段。一旦遇到大批量使用正则表达式的情况(例如网络爬虫)可以说基本上就抓瞎了。这篇文章我将带领大家利用 Python 来学习一下正则表达式。在阅读这篇文章前你需要掌握 Python 基础知识,或者具有其他开发语言的基础知识也可以,因为基本上每种语言使用正则表达式的方式都是类似的。

零、正则表达式基础

1.提取字符(串) 有时我们需要从一个字符串中获取一段内容,这段内容可能是一个字符也可能是一段字符串,如果用逐字对比遍历的话不仅耗时耗力而且还容易出错。那么这个时候我们就可以用到正则表达式中的 字符匹配 功能。正则表达式为我们提供了 4 种字符匹配的方法,见下表:

语法 说明 例子 可匹配字符串
. 匹配除了换行符 “\n” 以外的任意字符 a.b acb、adb、a2b、a~b
\ 转义,将转移字符后面的一个字符改变原来的意思 a[b\.\\]c abc、a.c、a\c
[] 匹配括号内的任意字符 a[b,c,d,e]f abd、acf、adf、aef
[^] 除了括号内的字符外,其他的字符都匹配 aa,b,c,d,ef a1f、a#f、azf、agf

2.预定义字符 所谓预定义字符就是正则表达式中为我们预留的专门用来匹配格式化内容的字符,例如匹配数字用的 \d 和匹配空白符的 \s 等等。我们可以利用预定义字符快速的匹配出一个字符串中符合要求的内容。预定义字符匹配的内容,同样也可以利用前面所讲的字符匹配的方式匹配出来,但是代码量会相对来说多一点。下表所列的就是预定义字符:

语法 说明 例子 可匹配字符串
^ 以什么字符串开始 ^123 123abc、123321、123zxc
$ 以什么字符串结尾 123$ abc123、321123、zxc123
\b 匹配单词边界,不匹配任何字符 \basd\b asd
\d 匹配数字0-9 zx\dc zx1c、zx2c、zx5c
\D 匹配非数字 zx\Dc zxvc、zx$c、zx&c
\s 匹配空白符 zx\sc zx c
\S 匹配非空白符 zx\Sc zxac、zx1c、zxtc
\w 匹配字母、数字和下划线 zx\wc zxdc、zx1c、zx_c
\W 匹配非字母、数字和下划线 zx\Wc zx c、zx$c、zx(c

在预定义字符中有如下几点需要注意:

  • \b 匹配的只是一个位置,这个位置的一侧是构成单词的字符,另一侧为非单词字符、字符串的开始或结束位置。\b 是零宽度。
  • \w 在不同编码语言中匹配的范围是不一样的,在使用 ASCII 码的语言中匹配的是 [a-zA-Z0-9] ,而在使用 Unicode 码的语言中匹配的是 [a-zA-Z0-9] 和汉字、全角符号等特殊字符。

3.限制数量 在某些情况下我们需要匹配重复的内容,这时我们可以使用 数量限定 模式来进行操作。数量限定如下表:

语法 说明 例子 可匹配字符串
* 匹配0到多次 zxc* zx、zxccccc
+ 匹配1次到多次 zxc+ zxc、zxccccc
? 匹配0次或1次 zxc? zxc、zx
{m} 匹配m次 zxc{3}vb zxcccvb
{m,} 匹配m次或多次 zxc{3,}vb zxcccvb、zxccccccccvb
{,n} 匹配0次到n次 zxc{,3}vb zxvb、zxcvb、zxccvb、zxcccvb
{m,n} 匹配m次到n次 zxc{1,3} zxcvb、zxccvb、zxcccvb

4.断言 断言,又称零宽断言,指的是当断言表达式为 True 时才进行匹配,但是并不匹配断言表达式内容。和 ^ 代表开头, $ 代表结尾, \b 代表单词边界一样,先行断言和后行断言也有类似的作用,它们只匹配某些位置,在匹配过程中,不占用字符,所以被称为零宽。所谓位置,是指字符串中第一个字符的左边、最后一个字符的右边以及相邻字符的中间。零宽断言表达式有四种:

  • 零宽度负回顾后发断言 (?<!exp),表达式不成立时匹配断言后面的位置,成立时不匹配。例如 \w+(?<zxc)\d,匹配不以 zxc 结尾的字符串;
  • 零宽度负回顾先行断言 (?!exp),表达式匹配断言前面的位置,成立时则不匹配。例如:\d(?!zxc)\w+,匹配不以 zxc 开头的字符串;
  • 先行断言 (?=exp),断言为真时匹配断言前面的位置,例如要在 “a regular expression” 这个字符串中追匹配出 regular 中的 re ,我们可以这么写 re(?=gular);
  • 后发断言 (?<=exp),断言为真时匹配断言后面的位置,例如对 “egex represents regular expression” 这个字符串要想匹配除 regex 和 regular 之外的re,可以用 re(?!g),该表达式限定了re右边的位置,这个位置后面不是字符g。先行和后发的区别就在于该位置之后的字符能否匹配括号中的表达式。

5.贪婪/非贪婪 正则表达式会尽可能多的去匹配字符,这被称为贪婪模式,贪婪模式是正则表达式默认的模式。但是有时候贪婪模式会给我们造成不必要的困扰,例如我们要匹配字符串 “Jack123Chen123Chen” 中的 “Jack123Chen”,但是贪婪模式匹配出的却是 “Jack123Chen123Chen”,这时我们就需要用到非贪婪模式来解决这个问题,非贪婪模式常用的表达式如下:

语法 说明
*? 匹配0次或多次,但要尽可能少重复
+? 匹配1次或多次,但要尽可能少重复
?? 匹配0次或1次,但要尽可能少重复
{m,}? 匹配m次或多次,但要尽可能少重复
{m,n}? 匹配m次或n次,但要尽可能少重复

6.其他 上述内容在正则表达式中都是常用的,下面我们再来看看不常用到的,但是功能同样强大的语法。

  • OR 匹配又称匹配分支,也就是说只要有一个分支匹配就算匹配,这和我们在开发中使用的 OR 语句类似。OR 匹配利用 | 分割分支,例如我们需要匹配出英文姓名,但是在英文中姓和名中间有可能是以 · 分割,也有可能是以空格分隔,这时我们就可以利用 OR 匹配来处理这个问题。格式如下:[A-Za-z]+·[A-Za-z]+|[A-Za-z]+\s[A-Za-z]+
  • 组合,将几个项组合为一个单元,这个单元可通过* + ? | 等符号加以修饰,而且可以记住和这个组合相匹配的字符串以提供伺候的引用使用。分组使用 () 来表示。例如获取日期的正则表达式可以这么写:\d{4}-(0[1-9]|1[0-2])-(0[1-9]|12|3[01])。第一个分组 (0[1-9]|1[0-2]) 代表月的正则匹配,第二个分组 (0[1-9]|12|3[01]) 代表日的正则匹配。

一、Python 使用正则表达式

在 Python 中使用正则表达式很简单,re 模块向我们提供了正则表达式的支持。使用步骤一共三步:

  • 将正则表达式字符串转换为 Pattern 的实例;
  • 使用 Pattern 实例去处理要匹配的字符,匹配结果是一个 Match 实例;
  • 利用 Match 实例去进行之后的操作。

在 Python 中我们常用的 re 的方法有六种,分别是: compile 、 match 、 search 、 findall 、 split 和 sub ,下面就针对这六种方法进行一下讲解。

compile compile 方法的作用是将正则表达式字符串转化为 Pattern 实例,它具有两个参数 pattern 和 flags ,pattern 参数类型是 string 类型,接收的是正则表达式字符串,flags 类型是 int 类型,接收的是匹配模式的编号,flags 参数是非必填项,默认值为 0 (忽略大小写)。flags 匹配模式有如下 6 种:

匹配模式 说明
re.I 忽略大小写
re.M 多行匹配模式
re.S 任意匹配模式
re.L 预定义字符匹配模式
re.U 限定字符匹配模式
re.V 详细模式

上述六种模式在实际开发中很少用到,我们只需要了解即可。 使用 compile 很简单,如下:

import re ​
pattern = re.compile(r'\d')

2.match match 的作用是利用 Pattern 实例,从字符串左侧开始匹配,如果匹配到就返回一个 Match 实例,如果没有匹配到就返回 None。

import re ​
def getMatch(message):
  pattern = re.compile(r'(\d{4}[-年])(\d{2}[-月])(\d{2}日{0,1})')
  match = re.match(pattern, message)
  if match:
    print(match.groups())
    for item in match.groups():
      print(item)
  else:
    print("没匹配上") ​
​
if __name__ == '__main__':
  message = "2019年01月23日大会开始"
  getMatch(message)
  message = "会议于2019-01-23召开"
  getMatch(message)

在代码中我们使用了 groups 方法,这个方法用来获取匹配出来的字符串组。到这里过一会有很多读者感到纳闷,为什么第一段内容能匹配出来年月日,而第二段内容不能呢?这是因为 match 方法是从字符串的起始位置匹配的。 代码运行结果如图:

3.search search 方法与 match 方法功能是一样的,只不过 search 方法是对整个字符串进行匹配。将前一小节代码中的 getMatch 方法进行改动,即可将第二段内容中的年月日匹配出来。

import re ​
def getMatch(message):
  pattern = re.compile(r'(\d{4}[-年])(\d{2}[-月])(\d{2}日{0,1})')
  match = re.search(pattern, message)
  if match:
    print(match.groups())
    for item in match.groups():
      print(item)
  else:
    print("没匹配上") ​
​
if __name__ == '__main__':
  message = "2019年01月23日大会开始"
  getMatch(message)
  message = "会议于2019-01-23召开"
  getMatch(message)

上述代码运行结果如下图:

4.findall findall 方法的作用是匹配整个字符串,以列表的形式返回所有匹配结果。

import re ​
​
def getMatch(message):
  pattern = re.compile(r'\w+')
  match = re.findall(pattern, message)
  if match:
    print(match)
  else:
    print("没匹配上") ​
​
if __name__ == '__main__':
  message = "my name is 张三"
  getMatch(message)
  message = "张三 is me"
  getMatch(message)

代码运行结果如下图:

5.split split 方法是利用指定的字符来分割字符串。

import re ​
​
def getMatch(message):
  pattern = re.compile(r'-')
  match = re.split(pattern, message)
  if match:
    print(match)
  else:
    print("没匹配上") ​
​
if __name__ == '__main__':
  message = "2018-9-12"
  getMatch(message)
  message = "第一步-第二步-第三步-第四步-and more"
  getMatch(message)

上述代码运行结果如下图:

6.sub sub 方法用来替换字符串,它接受5个参数,其中常用的有三个:

  • pattern,Pattern 实例
  • string,等待替换的字符串
  • repl,表示替换的新字符串或需要执行的替换方法
  • count,替换次数,默认为0表示全部替换
import re ​
​
def getMatch(match):
  return match.group(0).replace(r'年龄', 'age') ​
​
if __name__ == '__main__':
  message = "your 年龄 ?"
  pattern=re.compile(r'\w+')
  print(re.sub(pattern,getMatch,message))

代码运行结果如下图:

三、总结

Python 中正则表达式使用起来非常方便,上面所展示的代码,完全可以直接复制出来稍加修改后放在项目中使用。内容不多,主要是讲解代码怎么使用,希望大家完全理解掌握了正则表达式的写法。

作者简介:
朱钢,笔名喵叔,国内某技术博客认证专家,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于一家初创公司,从事企业级安全监控系统的开发。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • python使用正则表达式提取网页URL的方法

    本文实例讲述了python使用正则表达式提取网页URL的方法.分享给大家供大家参考.具体实现方法如下: import re import urllib url="http://www.jb51.net" s=urllib.urlopen(url).read() ss=s.replace(" ","") urls=re.findall(r"<a.*?href=.*?<\/a>",ss,re.I) for i i

  • Python匹配中文的正则表达式

    正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大.得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同:但不用担心,不被支持的语法通常是不常用的部分. Python正则表达式简介 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 P

  • Python中正则表达式的详细教程

    1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我们想要从返回的页面内容提取出我们想要的内容就易如反掌了. 正则表达式的大致匹配过程是:     1.依次拿出表达式和文本中的字符比较,     2.如果每

  • Python 中文正则表达式笔记

    从字符串的角度来说,中文不如英文整齐.规范,这是不可避免的现实.本文结合网上资料以及个人经验,以 python 语言为例,稍作总结.欢迎补充或挑错. 一点经验 可以使用 repr()函数查看字串的原始格式.这对于写正则表达式有所帮助. Python 的 re模块有两个相似的函数:re.match(), re.search .两个函数的匹配过程完全一致,只是起点不同.match只从字串的开始位置进行匹配,如果失败,它就此放弃:而search则会锲而不舍地完全遍历整个字串中所有可能的位置,直到成功地

  • python利用正则表达式提取字符串

    前言 正则表达式的基础知识就不说了,有兴趣的可以点击这里,提取一般分两种情况,一种是提取在文本中提取单个位置的字符串,另一种是提取连续多个位置的字符串.日志分析会遇到这种情况,下面我会分别讲一下对应的方法. 一.单个位置的字符串提取 这种情况我们可以使用(.+?)这个正则表达式来提取. 举例,一个字符串"a123b",如果我们想提取ab之间的值123,可以使用findall配合正则表达式,这样会返回一个包含所以符合情况的list. 代码如下: import re str = "

  • PYTHON正则表达式 re模块使用说明

    首先,运行 Python 解释器,导入 re 模块并编译一个 RE: #!python Python 2.2.2 (#1, Feb 10 2003, 12:57:01) >>> import re >>> p = re.compile('[a-z]+') >>> p <_sre.SRE_Pattern object at 80c3c28> 现在,你可以试着用 RE 的 [a-z]+ 去匹配不同的字符串.一个空字符串将根本不能匹配,因为 +

  • 零基础写python爬虫之神器正则表达式

    接下来准备用糗百做一个爬虫的小例子. 但是在这之前,先详细的整理一下Python中的正则表达式的相关内容. 正则表达式在Python爬虫中的作用就像是老师点名时用的花名册一样,是必不可少的神兵利器. 一. 正则表达式基础 1.1.概念介绍 正则表达式是用于处理字符串的强大工具,它并不是Python的一部分. 其他编程语言中也有正则表达式的概念,区别只在于不同的编程语言实现支持的语法数量不同. 它拥有自己独特的语法以及一个独立的处理引擎,在提供了正则表达式的语言里,正则表达式的语法都是一样的. 下

  • python的正则表达式re模块的常用方法

    1.re的简介 使用python的re模块,尽管不能满足所有复杂的匹配情况,但足够在绝大多数情况下能够有效地实现对复杂字符串的分析并提取出相关信息.python 会将正则表达式转化为字节码,利用 C 语言的匹配引擎进行深度优先的匹配. 复制代码 代码如下: import re print re.__doc__ 可以查询re模块的功能信息,下面会结合几个例子说明. 2.re的正则表达式语法 正则表达式语法表如下: 语法 意义 说明 "." 任意字符 "^" 字符串开始

  • python正则表达式中的括号匹配问题

    问题: m = re.findall('[0-9]*4[0-9]*', '[4]') 可以匹配到4. m = re.findall('([0-9])*4([0-9])*', '[4]') 匹配不到4. 这是为什么呢?PS,这个是一个简化的说明,我要用的正则比这个复杂,所以要用到(),表示一个序列的匹配. 补充一点,我放在notepad++中用的时候,两种写法都能匹配出来,不知道为什么python中就不行了. 答案: python的正则中用()会进行匹配,所以返回结果是['',''],就是两个()

  • Python使用中文正则表达式匹配指定中文字符串的方法示例

    本文实例讲述了Python使用中文正则表达式匹配指定中文字符串的方法.分享给大家供大家参考,具体如下: 业务场景: 从中文字句中匹配出指定的中文子字符串 .这样的情况我在工作中遇到非常多, 特梳理总结如下. 难点: 处理GBK和utf8之类的字符编码, 同时正则匹配Pattern中包含汉字,要汉字正常发挥作用,必须非常谨慎.推荐最好统一为utf8编码,如果不是这种最优情况,也有酌情处理. 往往一个具有普适性的正则表达式会简化程序和代码的处理,使过程简洁和事半功倍,这往往是高手和菜鸟最显著的差别.

  • Python正则表达式如何进行字符串替换实例

    Python正则表达式在使用中会经常应用到字符串替换的代码.有很多人都不知道如何解决这个问题,下面的代码就告诉你其实这个问题无比的简单,希望你有所收获. 1.替换所有匹配的子串用newstring替换subject中所有与正则表达式regex匹配的子串 result, number = re.subn(regex, newstring, subject) 2.替换所有匹配的子串(使 用正则表达式对象) rereobj = re.compile(regex) result, number = re

  • python正则表达式re模块详细介绍

    本模块提供了和Perl里的正则表达式类似的功能,不关是正则表达式本身还是被搜索的字符串,都可以是Unicode字符,这点不用担心,python会处理地和Ascii字符一样漂亮. 正则表达式使用反斜杆(\)来转义特殊字符,使其可以匹配字符本身,而不是指定其他特殊的含义.这可能会和python字面意义上的字符串转义相冲突,这也许有些令人费解.比如,要匹配一个反斜杆本身,你也许要用'\\\\'来做为正则表达式的字符串,因为正则表达式要是\\,而字符串里,每个反斜杆都要写成\\. 你也可以在字符串前加上

随机推荐