正则表达式以及python的re模块介绍

2023-09-12 17:23:03

正则表达式

字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

所以我们判断一个字符串是否是合法的Email的方法是:

  1. 创建一个匹配Email的正则表达式;
  2. 用该正则表达式去匹配用户的输入来判断是否合法。

因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。

  • 基础

    \d 可以匹配一个数字
    \w 可以匹配一个字母或数字
    \s 匹配任意的空白字符。所谓空白字符,包括空格、tab键(制表符)、回车符、换行符等等。
    . 可以匹配匹配任意单个字符
    * 表示任意个字符(0个或多个)
    + 表示至少一个字符
    ? 表示0个或1个字符
    {n}表示n个字符
    {n,m}表示n~m个字符
    

    例子:

    '00\d'可以匹配'007'
    '\w\w\d'可以匹配'py3'
    'py.'可以匹配'pyc'、'pyo'、'py!'
    
    \d{3}\s+\d{3,8} :\d{3}表示匹配3个数字,\s可以匹配一个空格,所以\s+表示至少有一个空格
    

    如果要匹配’010-12345’这样的号码呢?由于’-'是特殊字符,在正则表达式中,要用\转义,所以,正则是

    \d{3}\-\d{3,8}
    

    正则表达式内部:如果有特殊字符也是需要手动转义的

    • 进阶

      要做更精确地匹配,可以用[]表示范围,[]内是所有可选项

      a-b :表示从a~b的所有字符 
      [0-9a-zA-Z\_]  可以匹配一个数字、字母或者下划线
      [0-9a-zA-Z\_]+ 可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z'
      [a-zA-Z][0-9a-zA-Z\_]可以匹配由字母开头,后接任意个由一个数字、字母或者下划线组成的字符串
      [a-zA-Z][0-9a-z]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)
      
      A|B  表示:A或B,所以(P|p)ython可以匹配'Python'或者'python'。
      ^    表示行的开头,^\d表示必须以数字开头。
      $    表示行的结束,\d$表示必须以数字结束。
      ^py$ 表示结果只能是py
      

字符转义的理解

在任意编程语言中,定义的一个用户的一个字符串,在被加载的时候不是不变的,比如s = “\n"会被解析成为一个换号,但是当我们需要输出”\n"时,我们要这样写s = "\\n",也就是在前面再加一个"\",表示后面的这个斜杠是一个普通斜杠,表示它不用被转义。简单点说,一个字符串默认有可能会被解析成一个特殊的含义(换行),但是我们不想要这样,所以需要自己去转义这个特殊字符,使得得到我们想要的结果。一般情况下,都是使用\来转义字符。

也就是说,转义特殊字符需要手动在前面加\,python中很方便

  • 正则表达式

    在写正则表达式时,对于一些特殊字符的匹配也是需要转义的。比如想要匹配一些特殊的字符,比如-,-在正则表达式中就是个特殊字符,用来表示一个范围,如果要匹配"1-1"这样的情况,正则表达式是"\d\-\d",而不是"\d-\d"

  • python

    在python中可以直接使用re.match函数去匹配正则表达式

    但是,py中定义了一个字符串,很有可能被python给转义成其他东西了,所以需要转义,py有两种方法

    • 方法1:使用只读参数r,强制不转义

      s = r'ABC\-001'
      
    • 方法2:re.escape

      转义特殊字符需要手动在前面加\,python中有现成的api,可以将给定字符串中的所有特殊字符前面都加上\,也就是re.escape()函数

      pattern1 = re.escape("a*b") # 相当于pattern1 = a\*b
      pattern2 = "a\*b" # pattern2和pattern1一样
      
  • 例子

    import re
    
    # 想要匹配的表达式是'a\-',但是py把斜杠转义了,导致pattern从'a\\-'变成了'a\-',导致匹配到'a-'也成功了
    pattern = 'a\\-'
    input = 'a-'
    res = re.match(pattern, input)  # 匹配成功
    print(res)
    
    # 正确写法
    pattern = r'a\\-'  # 只读,不解析
    input = 'a\-'
    res = re.match(pattern, input)  # 成功
    print(res)
    
    pattern = re.escape('a\\-')  # 调用api自动加\
    input = 'a\-'
    res = re.match(pattern, input)  # 成功
    print(res)
    

re.match函数

match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None

例子

import re

pattern = r".a."
url = "Aa9"

if re.match(pattern, url):
    print("匹配成功!") 
else:
    print("匹配失败!")
# 输出: 匹配成功

匹配邮箱

# 匹配邮箱
pattern = r'^[a-zA-Z0-9\.]+@[a-zA-Z0-9\.]+\.com$'
pattern = r'^[\w\.]+@[\w\.]+\.com$' # 简写

print(re.match(pattern,'someone@gmail.com'))
print(re.match(pattern,'bill.gates@microsoft.com'))
  • 扩展

    可以提取出带名字的Email地址:

    tom@voyager.org => Tom Paris

    bob@example.com => bob

    import re
    
    def name_of_email(addr):
        re_name_of_email = re.compile(r'<?([a-zA-Z\s]+)?>?\s?([0-9a-zA-Z]+)*@[0-9a-zA-Z]+.org')
        m = re_name_of_email.match(addr)
        print(m.groups())
        if m.group(1):
            return m.group(1).strip()
        else:
            return m.group(2)
    
    # 测试:
    assert name_of_email('<Tom Paris> tom@voyager.org') == 'Tom Paris'
    assert name_of_email('tom@voyager.org') == 'tom'print('ok')
    

re.escape函数

reference:https://www.python100.com/html/79913.html

在Python的正则表达式(re)模块中,re.escape函数是一个非常有用的工具,它用于将一个字符串中的特殊字符转义成正则表达式中的普通字符。在使用正则表达式进行字符串的匹配时,如果字符串中包含了正则表达式的特殊字符,那么就需要使用re.escape函数来对这些特殊字符进行转义,让它们变成普通字符,以保证匹配的准确性。

简单点说,re.escape函数就是将字符串中的所有特殊字符前面全部加上\

语法如下

re.escape(string)

其中,string是需要进行转义的字符串参数。

例子:

import re

pattern1 = re.escape("a*b") # 结果是pattern1 = a\*b
pattern2 = "a\*b" # pattern2和pattern1一样
str = "a*b"

if re.match(pattern1, str) and re.match(pattern2, str):
    print("两种方式都可以匹配!")
else:
    print("匹配失败!")

切分字符串

用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:

>>> 'a b   c'.split(' ')
['a', 'b', '', '', 'c']

嗯,无法识别连续的空格,用正则表达式试试:

>>> re.split(r'\s+', 'a b   c')
['a', 'b', 'c']

无论多少个空格都可以正常分割。加入,试试:

>>> re.split(r'[\s\,]+', 'a,b, c  d')
['a', 'b', 'c', 'd']

再加入;试试:

>>> re.split(r'[\s\,\;]+', 'a,b;; c  d')
['a', 'b', 'c', 'd']

分组

除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:

^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
>>> m
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'

如果正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。

注意到group(0)永远是与整个正则表达式相匹配的字符串,group(1)group(2)……表示第1、2、……个子串。

贪婪匹配

最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0

>>> re.match(r'^(\d+)(0*)$', '102300').groups()
('102300', '')

由于\d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了。

必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪匹配:

>>> re.match(r'^(\d+?)(0*)$', '102300').groups()
('1023', '00')

编译

当我们在Python中使用正则表达式时,re模块内部会干两件事情:

  1. 编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
  2. 用编译后的正则表达式去匹配字符串。

如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:

>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')

编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对应的方法时不用给出正则字符串。

更多推荐

5.k8s jenkins集成k8s一键发布案例

文章目录前言一、jenkins配置1.1jenkins配置git1.2jenkins配置maven1.3jenkins配置java二、jenkins流水线配置2.1.新增项目2.2springboot项目配置git仓库2.3springboot项目配置maven打包2.4系统配置ssh到hadoop1配置,也就是k8s

MYSQL01高级_Linux版安装、各级别字符集、字符集与比较规则、SQL大小写规范

文章目录①.MySQL-linux版安装②.字符集的相关操作③.各级别的字符集④.字符集与比较规则(了解)⑤.SQL大小写规范⑥.sql_mode的合理设置①.MySQL-linux版安装①.进入mysql官网,找到安装文件②.将抽取出来的文件放在linux下的opt下MySQLCommunityServer社区版本,

创邻科技,位居IDC MarketScape中国图数据库市场领导者类别

图数据库,正进入市场发展的新阶段。随着中国经济社会数字化转型加速,数据成为新型生产要素。如何存储并管理海量数据,挖掘数据价值,打破原有增长天花板,成为企业重塑商业价值的关键。存量经济时代更需要深层关系挖掘,打造更深刻的客户洞察和画像,从点、面、网来做网络分析。作为数字化企业构建相对竞争优势的关键技术,图数据库正大步迈进

企业级通用低代码开发平台——一二三应用开发平台发布4.2开源版本,回顾与展望

背景今年三月初,确定了自己将来很长一段时间要做的事情,再启程,从头开始,研发一套应用开发平台,完全开源,详见https://blog.csdn.net/seawaving/article/details/129334330。从头开始,不是从零开始,大量的技术选型工作,平台设计与实现工作,都已实现,需要的大多是迁移和优化

开源在医疗健康领域的应用

🌷🍁博主猫头虎带您GotoNewWorld.✨🍁🦄博客首页——猫头虎的博客🎐🐳《面试题大全专栏》文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大

三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析

三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析三维模型的轻量化压缩是一项技术挑战,特别是在处理复杂的3DTile格式时。下面列举了一些处理过程中可能遇到的常见问题以及相应的处理方法:模型精度损失:在进行压缩处理时,由于顶点减少或数据精度降低,可能导致模型的精度损失,表现为模型变形或者细节丢失。对此,我们

基础数据结构与算法总结3(附有完整代码,适合小白)

目录前言13,哈希表14,二叉搜索树14.1,二叉搜索树完整代码如下15,平衡二叉树15.1,平衡二叉树完整代码如下:16,排序篇16.1,插入排序(稳定)16.2,插入排序完整代码16.3,冒泡排序(稳定)16.4,冒泡排序完整代码16.5,快速排序(不稳定)16.6,快速排序完整代码16.7,合并排序(稳定)16.

爬虫框架Scrapy学习笔记-2

前言Scrapy是一个功能强大的Python爬虫框架,它被广泛用于抓取和处理互联网上的数据。本文将介绍Scrapy框架的架构概览、工作流程、安装步骤以及一个示例爬虫的详细说明,旨在帮助初学者了解如何使用Scrapy来构建和运行自己的网络爬虫。爬虫框架Scrapy学习笔记-1文章目录前言Scrapy架构概览Scrapy工

OpenMV与STM32之间的通信(附源码)

本篇文章旨在记录我电赛期间使用openmv和stm32单片机之间进行串口通信,将openmv识别到的坐标传输给单片机。背景是基于2023年全国大学生电子设计大赛E题:舵机云台追踪识别。单片机的串口通信原理我便不再详细讲解,下面直接上代码分析。值得注意的是接线:RX——>TXTX——>RX单片机和OPENMV必须共地非常

Python爬虫技巧:使用代理IP和User-Agent应对反爬虫机制

在当今的网络环境中,反爬虫机制广泛应用于各个网站,为爬虫程序增加了困难。然而,作为一名Python爬虫开发者,我们可以利用一些技巧应对这些反爬虫措施。本文将分享一个重要的爬虫技巧:使用代理IP和User-Agent来应对反爬虫机制,帮助您更有效地进行数据爬取。1.使用代理IP许多网站通过监控来自同一IP地址的高频请求来

从零开始—【Mac系统】MacOS配置Java环境变量

系统环境说明AppleM1macOSVentura版本13.5.21.下载JDK安装包Oracle官网下载地址JDK下载【注:推荐下载JDK8Oracle官网JDK8下载】关于JDK、JRE、JVM的关系说明JDK(JavaDevelopmentKit,Java开发工具包),是整个JAVA的核心,包括JRE,很多Jav

热文推荐