正则表达式高阶技巧之匹配模式(使用python实现)

匹配模式

    • 介绍
      • 不区分大小写模式
        • 模式的指定方式
        • 应用
      • 单行模式
      • 多行模式
      • 注释模式
      • 其它模式
    • 修饰符的作用范围

介绍

  • 我们在正则中所说得匹配模式(match mode),指的是匹配时使用的规则。设置特定的匹配模式,可能会改变对正则表达式的识别,也可能会改变正则表达式中字符的匹配规定
  • 常见的匹配模式一共有四种:不区分大小写模式、单行模式、多行模式、注释模式

不区分大小写模式

  • 在日常使用中,用户可能关心的只是文本的意义,而不是它具体形式。比如单词the,在句子中写作the,在句子开头写做The,还可能为了表示强调写作THE;可是用户可能不关心大小写,只希望找到所有的the
  • 为了实现上述需求,我们可以使用字符组[tT][hH][eE],这样的写法是没有问题的,但是如果单词较长,写起来就是比较麻烦的。比如:beautiful就要写成[bB][eE][aA][uU][tT][iI][fF][uU][lL]。更重要的是,这样的表达式不够直观,很难明白此表达式要匹配的是beautiful
  • 为了解决上述的问题,正则表达式提供了不区分大小写的匹配模式,指定此模式之后,在正则表达式中可以直接写the,就可以匹配the、THE、The、THe等等各种大小写形式的the,提升了直观程度,还大大降低了理解的难度

模式的指定方式

  • 在了解此模式的应用实例之前,必须要先了解模式的指定方式。通常是有两种方法来指定匹配模式的:以模式修饰符指定,或者以预定义常量作为特殊参数传入来指定

模式修饰符

  • 模式修饰符即模式对应的单个字符,使用时将其填入特定结构(?modifier)(其中modifier为模式修饰符),嵌在正则表达式的开头。比如不区分大小写的模式对应的模式修饰符是i(case Insensitive),对于the来指定此模式,完整的表达式为(?i)the
    如下举例:
import re
re.search(r"(?i)beautiful",'beautiful') is not None
re.search(r"(?i)beautiful",'Beautiful') is not None
re.search(r"(?i)beautiful",'BEAUTIFUL') is not None

在这里插入图片描述
预定义好的常量作为特殊参数传入来指定

  • 我们可以使用预定义好的常量作为参数,传入正则函数
  • 在python中不区分大小写的预定义常量是Re类的静态成员re.IGNORECASE(一般来说。它是某个类的静态成员)
语言常量
pythonre.I或re.IGNORECASE

如下举例:

import re
re.search(r"beautiful",'beautiful',re.I) is not None
re.search(r"beautiful",'Beautiful',re.IGNORECASE) is not None

在这里插入图片描述

  • 上述的两种指定方式,模式描述符较为通用,因为在常用的语言中写法基本相同,而预定义常量在不同语言中写法不同,不过上述的两种形式的效果是相同的:无论是以那种方式,只要指定不区分大小写模式,正则表达式在匹配时,就不会区分同一个字母的大小写形式,即(?i)the(?i)THE是完全等价的

应用

  • 在之前匹配HTML最终tag的例子中,比如匹配超链接tag的正则表达式、匹配图片tag及网页标题tag的正则表达式,虽然在HTML规范推荐tag名都使用小写字母,但类似的<IMG>的tag还是可能出现的,为了同时兼容大写字母,可以使用不区分大小写模式,如下表格:
描述表达式
提取超链接(?i)<a\s+href\s*=\s*["']?([^"'\s]+)["']?>([^<]+)</a>
提取标题(?i)<head>([^>]+)</head>
提取图片(?i)<img\s[^>]*?src=['"]?([^'"]+)['"]?[^>]*>

单行模式

  • 元字符.几乎可以匹配任何字符,唯有换行符\n是例外。但是,有是否确实需要匹配“任何字符”,比如我们在处理爬取到的HTML源码时,经常需要跨越多行取数据,如下:
<script type="text/javascript">
...code...
...code...
</script>
  • 正则文档里一般都会说明“.不能匹配换行符”,不过部分人并不阅读与深究文档,所以认为.点号能匹配任何字符,当然也包括换行符,所以直接想法就是<script\s.*?</script>
  • 因为这段代码出现了换行符,所以.*?的匹配最多只能进行到第一行末尾,可以使用[\s\S]之类的字符组匹配“任意字符”,所以正则表达式<script\s[\s\S]*?</script>能解决问题
  • 不过对于大部分人来说,点号更加自然,也更加直观简洁,所以正则表达式提供单行模式,在这个模式下,所有的文本似乎只在一行里,换行符是这一行中的“普通字符”,所以可以使用.来进行匹配
  • 重点在于是将单行模式中的文本看成一行
  • 单行模式对应的模式修饰符是s(Single line),所以如果要使用单行模式,只需要在表达式的开头用(?s)指定,因此上面的表达式可以修改为(?s)<script\s.*?</script>

预定义常量如下:

语言常量
pythonre.S或re.DOTALL

多行模式

  • “多行模式”听起来是与上述的“单行模式”对应的,但其实这两个模式是没有任何联系的
  • 单行模式影响的是.点号的匹配规则:在默认的模式下,点号.可以匹配除换行符之外的任何字符,在单行模式下点号可以匹配包括换行符在内的任何字符
  • 多行模式影响的是^$的匹配规则:在默认的模式下^$匹配的是整个字符串的起始位置与结束位置,但是在多行模式下,它们也能匹配字符串内部某一行文本的起始位置和结束位置
  • 如下举例,需要找到下面文本中所有以数字字符开头的行:
1 one
No ycx
Yes wy
2 two
  • 为解决此问题,需要定位到每一行的起始位置,尝试匹配一个数字字符,如果成功,则匹配之后的整行文本。多行模式的模式修饰符是m(Multiline),所以在表达式中的开头用(?m)指定多行模式,这样^就可以定位到字符串内部的每一行的起始位置;匹配数字字符的表达式为\d,因为没有指定单行模式。.点号是不能匹配换行符的,.*可以匹配数字字符之后的整行文本,所以表达式就是(?m)\d.*

如下测试:

import re

multiStr = """
1 one
No ycx
Yes wy
2 two
"""

multiRegex = r"(?m)\d.*"
for line in re.findall(multiRegex, multiStr):
    print(line)

在这里插入图片描述

  • 还可以利用多行模式下的$,给每一行末尾添加英文句号.,如下:
import re
multiStr = """1 one
No ycx
Yes wy
2 two"""
print(re.sub(r'(?m)$','.',multiStr))

在这里插入图片描述

  • 预定义常量如下:
语言常量
pythonre.M或re.MUTILINE

注释模式

  • 在某些情况下,用到的正则表达式可能是非常复杂的,不但难以编写和阅读,也难以维护,如果正则表达式也可以像编程语言源代码那样,可以添加注释,阅读与维护就容易多了
  • 为解决上述问题,多数语言是支持使用(?#comment)的记法添加注释,comment是注释内容。所以,在我们的表达式^\d.*?$就可以写成这样:^(?#start of the line)\d(?#digit).*?(?#rest of the line)
  • **.NET、Python、Ruby、PHP都是支持这种写法的,Java和JavScript则不支持,不过,还有一种注释的写法是各种语言都支持的,就是使用注释模式,此时,正则表达式对应的字符串可以跨越很多行,如下举例:
import re
multiStr = """1 one
No ycx
Yes wy
2 two"""

LineBeginRegex = r"""
(?mx) #enable multiline and extended mode
^    # start of the line
\d   #digit
.*   # est of the line
$    #end of the line
"""
re.findall(LineBeginRegex, multiStr)

在这里插入图片描述

  • 在注释模式下,正则表达式内部的空白字符都会被忽略(一般来说,只要是ASCII编码中的空白字符,Unicode编码中的空白字符清空不定),注释则以#comment的形式添加在正则表达式内部,每一条注释从#开始,到行末结束。在许多的文档,都是用这种模式来解释较为复杂的表达式,并且会使用缩进表示层级结构,这样就更加方便阅读和维护。
  • 如下举例匹配日期的正则表达式((?x)(\d{4})-(\d{2})-(\d{2})),在注释模式下的展开:
dateRegex=r"""
(?x)        # enable multiline ans extended mode
(           # start of the regex
    (\d{4}) # year
    -       # dash
    (\d{2}) # month
    -       # dash
    (\d{2}) # day
)           # end of the regex
"""
re.search(dateRegex,"2022-01-02").group()

在这里插入图片描述

  • 注释模式对应的修饰符是x(extended mode,扩展模式,但是更常见的写法是free-spacing mode,宽松格式模式)
  • 预定义常量如下:
语言常量
pythonre.X或re.VERROSE
  • 在上述例子,我们同时制定了两种模式:多行模式与注释模式。注释模式的x与多行模式的m,合在一起写作(?mx)。如果需要同时使用多种匹配模式,只要在(?modifier)中将模式修饰符排列起来即可
  • 如果希望同时使用多行模式与注释模式,使用预定义常量该怎么做?答案是,使用位运算符|,通常来说对应的预定义常量都是int类型,所以多个值进行按位与的结果,并不会彼此干扰,在python中是这样的re.M | re.X,如下:
import re

multiStr = """1 one
No ycx
Yes wy
2 two"""

LineBeginRegex = r"""
^    # start of the line
\d   #digit
.*   # est of the line
$    #end of the line
"""
re.findall(LineBeginRegex, multiStr, re.M | re.X)

在这里插入图片描述

其它模式

python的还包含有其他模式(这里仅列举两种,更多的请查阅文档):

  • re.U或re.UNICODE:在此模式下。\d \w \s等字符组简记法的匹配规则会发生改变,比如\w能匹配Unicode中的“单词字符”,包括中文字符,\d也能匹配1、2之类的全角数字字符,对应的模式修饰符是u
  • re.A或re.UNICODE:因为在python 3以上的版本中,正则表达式默认采用Unicode匹配规则,如果希望\d \w等字符组简记法恢复到ASCII匹配规则,可以使用此模式,对应的模式修饰符是a

修饰符的作用范围

  • 常见的模式修饰符为(?modifier)的形式,它表示从现在开始使用此模式,通常的做法是将它写在正则表达式的开头,表示整个正则表达式都指定使用此模式;如果它出现正则表达式中,则表示此模式从这里开始生效,但是在python中情况不同,只要模式修饰符(?modifier)出现,无论出现在什么位置,都对整个正则表达式生效;如下:
re.search(r"t(?i)he","THE").group()

在这里插入图片描述

  • 如果模式修饰符出现在某个括号内,如((?modifier).....)那它的作用范围只限于括号内部,此模式也可记为(?modifier:.....)

如下举例:

正则表达式可匹配的文本
t(?i)hetHE the tHe thE
th(?i)ethe thE
t((?i)h)etHe the
t(?i:h)etHe the
  • 模式修饰符对正则表达式的操作性更强,因为预定义常量指定的匹配模式是对整个正则表达式生效的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/664.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

业内人士真心话,软件测试是没有前途的,我慌了......

我在测试行业爬模滚打7年&#xff0c;从点点点的功能测试到现在成为高级测试&#xff0c;工资也翻了几倍。个人觉得&#xff0c;测试的前景并不差&#xff0c;只要自己肯努力。 我刚出来的时候是在鹅厂做外包的功能测试&#xff0c;天天点点点&#xff0c;很悠闲&#xff0c;点…

Spark SQL支持DataFrame操作的数据源

DataFrame提供统一接口加载和保存数据源中的数据&#xff0c;包括&#xff1a;结构化数据、Parquet文件、JSON文件、Hive表&#xff0c;以及通过JDBC连接外部数据源。一个DataFrame可以作为普通的RDD操作&#xff0c;也可以通过&#xff08;registerTempTable&#xff09;注册成…

嵌入式安防监控项目——实现真实数据的上传

目录 一、相关驱动开发 二、A9主框架 三、脚本及数据上传实验 https://www.yuque.com/uh1h8r/dqrma0/tx0fq08mw1ar1sor?singleDoc# 《常见问题》 上个笔记的相关问题 一、相关驱动开发 /* mpu6050六轴传感器 */ i2c138B0000 { /* #address-cells <1>…

web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation

文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…

SpringBoot-实用开发篇

SpringBoot开发实用篇开发实用篇中因为牵扯到SpringBoot整合各种各样的技术&#xff0c;所以在整合每一个技术之前&#xff0c;都会做一个快速的普及&#xff0c;这样的话内容整个开发实用篇所包含的内容就会比较多。在学习的时候&#xff0c;如果对某一个技术不是很清楚&#…

硬刚ChatGPT!文心一言能否为百度止颓?中国版ChatGPT“狂飙”的机会在哪儿?

文章目录目录产品背景发展历程科技简介主要功能合作伙伴结语文心一言 &#xff08;英文名&#xff1a;ERNIE Bot&#xff09; *是百度基于文心大模型技术推出的生成式对话产品&#xff0c;被外界誉为“中国版ChatGPT”&#xff0c;将于2023年3月份面向公众开放。 [40] 百度在人…

python自动化办公(二)

上接python自动化办公&#xff08;一&#xff09; 文章目录文件和目录操作使用shutil库文件查找globfnmatchhashlib文件和目录操作 使用shutil库 shutil库也是Python标准库&#xff0c;它可以处理文件、文件夹、压缩包&#xff0c;能实现文件复制、移动、压缩、解压缩等功能。…

Vue基础23之路由第二节

Vue基础23路由路由的query参数src/router/index.jsDetail.vueHomeMessage.vue路由的query参数命名路由src/router/index.jsHomeMessage.vueApp.vue总结路由的params参数src/router/index.jsHomeMessage.vueDetail.vue总结路由 路由的query参数 src/router/index.js //该文件专…

Gehpi的网络布局

Gehpi的网络布局1. 力引导布局2. 辅助布局布局是网络可视化中的重要概念&#xff0c;指将点和边通过某种策略进行排布&#xff0c;应尽可能满足以下4个原则&#xff1a; 节点均匀分布在有限的区域内避免边的交叉和弯曲保持边的长度一致整体布局能反映图内在的特性 Gephi的布局…

卷积神经网络

目录卷积神经网络概述神经网络原理卷积神经网络卷积层怎么控制输出数据&#xff1f;如何抓取特征池化层归一化层全连接层局部感受野权值共享多卷积核池化子采样多卷积层卷积神经网络的训练前向传播BackForward反向传播权值更新过程中的卷积网络结构层的排列规律层的尺寸设置规律…

web3:区块链共识机制系列-POS(Proof of Stake)股权证明算法

web3相关学习一并收录至该博客&#xff1a;web3学习博客目录大全 前情衔接&#xff1a;web3:区块链常见的几大共识机制及优缺点 目录前言算法公式与原理算法公式运作原理以Peer Coin为例缺陷优点缺点特点分类发展历程casper协议1.什么是无成本利益关系问题2.引入casper协议解决…

SpringBoot 动态操作定时任务(启动、停止、修改执行周期)增强版

前段时间编写了一篇博客SpringBoot 动态操作定时任务&#xff08;启动、停止、修改执行周期&#xff0c;该篇博客还是帮助了很多同学。 但是该篇博客中的方法有些不足的地方&#xff1a; 只能通过前端控制器controller手动注册任务。【具体的应该是我们提前配置好我们的任务&am…

selenium(4)-------自动化测试脚本(python)

webdriverAPI 一)定位元素的方式&#xff0c;必问 1.1)id来定位元素&#xff0c;前提是元素必须具有id属性&#xff0c;因为有的元素是没有id的 1.2)name&#xff0c;元素必须有name&#xff0c;并且必须全局唯一 1.3)tagname&#xff0c;元素是一定有的&#xff0c;但是必须全…

HTTP 缓存的工作原理

缓存是解决http1.1当中的性能问题主要手段。缓存可能存在于客户端浏览器上&#xff0c;也可以存在服务器上面&#xff0c;当使用过期缓存可能给用户展示的是错误的信息而导致一些bug。 HTTP 缓存&#xff1a;为当前请求复用前请求的响应 • 目标&#xff1a;减少时延&#xff1…

Python+Yolov8目标识别特征检测

Yolov8目标识别特征检测如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01;前言这篇博客针对<<Yolov8目标识别特征检测>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应用推荐…

3分钟看完-丄-Python自动化测试【项目实战解析】经验分享

目录&#xff1a;导读 引言 自动化测试 背景 测试团队 测试体系发展 测试平台 自动化测试现状 现状一&#xff1a; 现状二&#xff1a; 现状三&#xff1a; 现状四&#xff1a; 现状五&#xff1a; 现状六&#xff1a; 失败的背景 失败的经历 失败总结 引言 内…

Java多线程系列--synchronized的原理

原文网址&#xff1a;Java多线程系列--synchronized的原理_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java的synchronized的原理。 反编译出字节码 Test.java public class Test {private static Object LOCK new Object();public static int main(String[] args) {synchro…

动态矢量瓦片缓存库方案

目录 前言 二、实现步骤 1.将数据写入postgis数据库 2.将矢量瓦片数据写入缓存库 3.瓦片接口实现 4.瓦片局部更新接口实现 总结 前言 矢量瓦片作为webgis目前最优秀的数据格式&#xff0c;其主要特点就是解决了大批量数据在前端渲染时出现加载缓慢、卡顿的问题&#xff0…

LeetCode 112. 路径总和

LeetCode 112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶…

Python笔记 -- 文件和异常

文章目录1、文件1.1、with关键字1.2、逐行读取1.3、写入模式1.4、多行写入2、异常2.1、try-except-else2.2、pass1、文件 1.1、with关键字 with关键字用于自动管理资源 使用with可以让python在合适的时候释放资源 python会将文本解读为字符串 # -*- encoding:utf-8 -*- # 如…