python 正则表达式 断言 不定长表达式_MyEssay 之 Python正则表达式 —— 四种断言扩展的理解...

我们经常用正则表达式来检测一个字符串中包含某个子串,要表示一个字符串中不包含单个的某字符或某些字符也很容易,用[^...]形式就可以了。但是要表示一个字符串中不包含某个子串(由字符序列构成)的时候,用[^...]这种形式就不行了,此时就需要使用到四种正则表达式的扩展匹配了,即所谓的“正向前行匹配”  (?=...)、“负向前行匹配” (?!...)、"正向后行匹配" (?<=...)  、“负向后行匹配”(?文中的描述,从两个方面入手:

所谓的前行(lookahead)和后行(lookbehind),其实就是向前看和向后看的意思。正则表达式引擎在执行字符串和表达式匹配时,会从头到尾(从前到后)连续扫描字符串中的字符,设想有一个扫描指针指向字符边界处并随匹配过程移动。前行断言,是当扫描指针位于某个位置时,引擎会尝试匹配指针还未扫过的字符,先于指针到达该字符,故称为前行。后行断言,引擎会尝试匹配指针已扫过的字符,后于指针到达该字符,故称为后行。

记忆方式:后行断言(?<=pattern)、(?

所谓的正向(positive)和负向(negative):正向就表示匹配括号中的表达式,负向表示不匹配。

记忆方式:不等于(!=)、逻辑非(!)都是用!号来表示,所以有!号的形式表示不匹配、负向;将!号换成=号,就表示匹配、正向。

我们特别需要注意的一点是,对于后行方式的两种断言(?<=...)和(?

line0 = ‘?#?def???func(funcName, funcParam, funcTime=360) ‘

line1 = ‘?def???func(funcName, funcParam, funcTime=360) ‘

line2 = "????obj1(param).func(‘func1‘, ‘param1‘, funcTime=150) # test"

line3 = "??obj2().funcTest(1)  # obj1(param).func(‘func1‘, ‘param1‘)"

我们希望字符串中包含对函数 func()的调用,即在被测试line中出现 "func("字符串,但是在被测line中却又不包含针对函数func的定义,即不能出现 “def func(” 字符串,并且def 和 func 之间可能包含多个空格。按照最直接的思路,为要匹配 "func(" 字符串,并且是在 "func(" 前面不出现 “def\s+”模式的字符串,所以首先考虑使用向后看的方法,即负向后行匹配方式来应用于line1,即 re.findall(r"(?

>>> re.findall(r"(?

[‘???func(‘]

"func"前为三个空格;这是为什么呢?原因是re引擎会去尝试找到一个 "\s*func\(" 模式的字符串,并且在这个字符串前面不会出现 "def?" 字符串(def后有一个空格),包含三个前置空格的 "???func(" 正好就能满足条件,首先它能够匹配 "\s*func\(" 的模式,并且这个字符串前面的是不含空格的 "def" 字符串,而不是在负向后行匹配断言(?

那么尝试将负向后行匹配断言中def后面的空格去掉,即修改为 re.findall("(?

>>> re.findall(r"(?

[‘??func(‘]

"func"前为两个空格——仔细分析会发现这是因为原因是re引擎会去尝试找到一个“\s*func\(”模式的字符串,并且在这个字符串前面不会出现“def”字符串(def后没有空格),包含2个前置空格的 "??func(" 就正好满足条件,因为包含2个空格的 "??func(" 字符串能够匹配 "\s*func\(" 的模式,并且这个字符串前面的是后接了一个空格的 "def?" 字符串,而不是在负向后行匹配断言pattern "(?

再尝试在负向后行匹配断言中在def后面使用\s+,即修改为  re.findall("(?

——所以,对于在 def 和 func之间包含了三个空格的line1,要想用负向后行断言来实现匹配,必须使用def后包含三个空格而func前无空格的 re.findall("(?

于是我们只能考虑采取负向前行断言来实现精确匹配,即 re.findall("^(?!.*def\s+func\().*func\(", line1),执行得到的结果为空列表[],同时我们使用正向前行断言来验证我们的匹配字符串使用正确,即执行 re.findall("^(?=.*def\s+func\().*func\(", line1),得到的结果为 [‘def   func(‘]

>>> re.findall("^(?!.*def\s+func\().*func\(", line1)

[]

>>> re.findall("^(?=.*def\s+func\().*func\(", line1)

[‘?def???func(‘]

—— 这说明我们的负向前行断言正好精确匹配到了 def 和 func 之间存在不定长度空格数的情况。

此处再来解析一下这里的负向前行断言的含义:"^(?!.*def\s+func\().*func\("  表示从line的起始位置开始向后搜索,不允许出现 ".*def\s+func\(" 这种模式的字符串,但又尝试在此前提下寻找能够匹配  ".*func\(" 模式的字符串,这也就正是我们所希望的过滤条件。此处的 (?!.*def\s+func\() 是不消耗任何字符串长度的

这里需要特别注意的是另外两种与 re.findall("^(?!.*def\s+func\().*func\(", line1) 很接近的匹配模式:

1、如果使用的是  re.findall("^(?!def\s+func\().*func\(", line1),执行的结果将不会是预期的空列表,而是 [‘ def???func(‘],这是因为这种写法,RE引擎将会尝试搜索是否存在起始位置开始不是 "def\s+func\(" 而是 ".*func\(" 的字符串,但是line1中的"def"前面正好有一个空格,所以RE引擎发现从开始位置处搜索到的是带一个前置空格的 "?def\s+func\(" 模式的字符串,而不是负向前表达式中没有空格的 "def\s+func\(" 模式字符串,所以会匹配成功。

2、如果使用的是 re.findall("(?!.*def\s+func\().*func\(", line1),执行的结果也不会是预期的空列表,而是 [ ‘ef???func(‘ ],这是因为如果pattern中没有了^字符,就不是要求line1从开始就必须满足匹配条件,而是line1中任意位置能够满足匹配条件都可以,所以line1中的 "ef???func(" 这个字符串就能满足匹配条件

—— 综上所述,建议尝试正则匹配“在xxx之前不出现yyy,且 xxx 和 yyy 之间可能存在其他不定长字符串”的场景时,优先考虑使用负向前行断言; 对于能够确定xxx和yyy之间是定长的情况下,可以使用负向后行断言

再例如考虑在line3中匹配 "func(" 字符串的时候,要求在 "func(" 前不能出现#符号,即要求func函数的调用语句没有被注释掉,因为 # 和 func( 之间的字符长度完全是随机未知的,故应该使用负向想前行断言方式的 re.findall("^(?!.*#.*func\().*func\(", line3),而不是 re.findall("(?

原文:http://www.cnblogs.com/xaviercd/p/5818731.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python爬虫请求头是什么意思_python爬虫请求头的使用

这篇文章我们来讲一下在网站建设中&#xff0c;python爬虫请求头的使用。本文对大家进行网站开发设计工作或者学习都有一定帮助&#xff0c;下面让我们进入正文。爬虫请求头网页获取&#xff1a;通过urlopen来进行获取requset.urlopen(url,data,timeout)第一个参数url即为URL&a…

复化科特斯公式matlab_matlab实现复化NewtonCotes公式求积分的程序应用和代码

命令窗口输入被积函数2120ttedt。输入应为&#xff1a;。Step2&#xff1a;执行函数。输入形式为mymulNewtonCotes(ft,a,b,m,n)&#xff1b;其中ft—被积函数&#xff0c;此体重&#xff0c;已经在第一步赋值&#xff1b;a—积分下限&#xff0c;本题中为0&#xff1b;b—积分…

单元格自适应宽度_最详细的Excel模块Openpyxl教程(二)-单元格操作详解

在以前的推文中&#xff0c;我们介绍了操作Excel的模块openpyxl的入门知识&#xff0c;相关推文可以从本公众号的底部相关菜单获取。接下来的推文我们来学习一下openpyxl这个python模块中的其他知识&#xff0c;本次推文我们来学习一下单元格&#xff08;cell&#xff09;操作的…

动态参数 maven_使用Jenkins Git参数实现分支标签动态选择

1.1 为什么要使用GIT参数&#xff1f;我们为什么要使用 git参数呢&#xff1f; 每个项目代码库都会有不同的分支&#xff0c;(如果你没有用多分支流水线的情况下)对于普通的流水线项目我们可以 让一条流水线来支持多个分支的发布&#xff0c;其实有时候你会发现每个分支的集成步…

走线和交互式布线_画PCB时,一些非常好的布线技巧

画PCB时&#xff0c;一些非常好的布线技巧布线是PCB设计过程中技巧最细、限定最高的&#xff0c;即使布了十几年布线的工程师也往往觉得自己不会布线&#xff0c;因为看到了形形色色的问题&#xff0c;知道了这根线布了出去就会导致什么恶果&#xff0c;所以&#xff0c;就变的…

相机裁剪旋转_怎么旋转视频画面角度

在用手机或相机拍摄视频时&#xff0c;有时候画面会出现镜像、画面倒转的情况&#xff0c;影响观看体验&#xff0c;那么视频怎么旋转才能将画面变为正常播放&#xff1f;有很多方法可以做到&#xff0c;以下我为你挑选了最简单的工具&#xff0c;详细给你说说&#xff1a;在线…

新代数控系统参数说明书_台湾新代宏程序编程书

点击右上角关注公众号&#xff0c;每天更新其实说起来宏就是用公式来加工零件的&#xff0c;比如说椭圆,如果没有宏的话&#xff0c;我们要逐点算出曲线上的点&#xff0c;然后慢慢来用直线逼近&#xff0c;如果是个光洁度要求很高的工件的话&#xff0c;那么需要计算很多的点&…

树莓派要mysql的密码_树莓派raspberry Pi 3B+系统中安装mysql过程中不提示输入密码,安装完后如何设置密码...

树莓派raspberry Pi 3B安装mysql未提示输入密码&#xff0c;安装后修改mysql密码默认密码使用mysql -uroot -p 命令连接mysql时&#xff0c;报错piraspberrypi:/ $ mysql -uroot -pEnter password:ERROR1698 (28000): Access denied for user rootlocalhost按照网上的说法&…

mysql中error 1786_mysql错误处理之ERROR1786(HY000)_MySQL

ERROR 1786 (HY000)【环境描述】msyql5.6.14【报错信息】执行create table ... select的时候遇到报错&#xff1a;db1 [test] [23:01:58]> create tablelgmnr_bak select * from lgmnr;ERROR 1786 (HY000): CREATE TABLE ... SELECTis forbidden when GLOBAL.ENFORCE_GTID_C…

深入mysql语言_MySQL对数据操作的一些深入语法

其他数据操作数据的操作也叫作crud&#xff1a;C&#xff1a;createR&#xff1a;readU&#xff1a;updateD&#xff1a;delete插入数据蠕虫复制就是在已有的数据的基础之上&#xff0c;将原来的数据进行复制&#xff0c;插入到相对应的表中&#xff01;语法规则&#xff1a;in…

MySQL查询多表定义实体类_自己设计一个 JAVA + MyBatis 解析实体类多表通用查询

先来处理一下查询的字段和用到的表吧//虽然我们使用的时候是实体&#xff0c;但最终还是要解析成sql的&#xff0c;那么我们需要想好解析成sql 时候所用到的东东&#xff0c;提前准备好class TableEntity {String tableName; //表的真正名称肯定是要的String nickName; //表名的…

mysql table catalog_hibernate 注解@table( catalog=)作用

在阿里云RDS新建库和用户&#xff0c;并分配权限&#xff0c;而且用客户端访问连接成功。但启动应用&#xff0c;并修改连接用户和库地址&#xff0c;报错(信息如下)&#xff01;字面意思是用户没有SELECT的权限&#xff0c;但客户端验证不是权限问题。经多步测试发现应用一直在…

mysql 导出数据库中的某张数据表_mysql 导出数据库中的某张数据表

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

pycharm 开发app_windows及mac下开发Excel, python+xlwings开发环境配置

背景&#xff1a;孩子他妈天天excel办公&#xff0c;看她每天大量重复性的工作&#xff0c;她是时候学习python来解放自己了&#xff0c;虽然我不用python ~ ~网络搜索 xlwings 是python下非常强大的处理Excel的库开发IDE选择Pycharm或者vs code配置开发环境&#xff0c;折腾了…

mysql 优化表_mysql里sql优化和表结构优化

开启慢查询日志 计入sqlshow variables like slow_query_log;//慢查询查看状态 OFF未开启 ON开启show variables like %log%;//没有使用索引的sql计入慢查询日志中set global log_queries_nor_using_indexes on;//开启log_queries_nor_using_indexes 为ON 记录未使用索引的查询…

sql server查询历史进程_学习笔记 | SequoiaDB SQL查询语句执行过程

本篇笔记将为大家介绍 SequoiaDB 巨杉数据库查询 SQL 语句的执行过程&#xff0c;以及查询语句执行过程中实例层、协调节点、编码节点、数据节点各自承担的功能。应用程序或用户想要从数据库查询需要的数据&#xff0c;首先通过 API 或 client 端连接数据库&#xff0c;将查询 …

服务器主机linux安装mysql_linux服务器上安装mysql

mysql版本&#xff1a;mysql-5.6.44-linux-glibc2.12-x86_64.tarlinux操作系统和版本信息&#xff1a;1、检查linux服务器上是否已安全mysql[rootlocalhost ~]# rpm -qa|grep -i mysql未安装则无任何信息返回&#xff0c;若已安装则会返回已安装的版本信息&#xff0c;可通过--…

mysql中rownum分页_Oracle数据库中rownum分页

测试人员在项目测试中发现查询结果列表分页的时候&#xff0c;有的数据在好几页中重复显示&#xff0c;有的则一次都不显示&#xff0c;经过分析sql&#xff0c;原来问题出在测试人员在项目测试中发现查询结果列表分页的时候&#xff0c;有的数据在好几页中重复显示&#xff0c…

python买东西_Python实战之ATM+购物车

学python一个月以来的第一个工程级别项目!!!!!1.首先分析项目需求:模拟实现一个ATM 购物商城程序额度 15000或自定义---->注册功能实现购物商城&#xff0c;买东西加入 购物车&#xff0c;调用信用卡接口结账----->购物车,支付可以提现&#xff0c;手续费5%----->提现…

multi source replication mysql_MySQL 5.7多源复制(Multi-Source Replication)

MySQL5.7.6以后开始支持多源复制Multi-Source Replication,可以将多个主的库同步到一台slave上&#xff0c;从而增加从的利用率&#xff0c;出节省了机器&#xff0c;也可用于备份。首先设置master_info_repository和relay_log_info_repository两个参数&#xff0c;这存储同步信…