在学习re.split函数的处理过程中,发现执行如下语句及返回与老猿预想的不一致:

>>> re.split('\W*','Hello,world')
['', 'H', 'e', 'l', 'l', 'o', '', 'w', 'o', 'r', 'l', 'd', '']

而老猿期望的是[’’, ‘Hello’, ‘’, ‘world’, ‘’],结果差异很大。

我们再看使用组模式匹配的结果:

>>> re.split('(\W*)','Hello,world')
['', '', 'H', '', 'e', '', 'l', '', 'l', '', 'o', ',', '', '', 'w', '', 'o', '', 'r', '', 'l', '', 'd', '', '']

也不是老猿期望的:[’’,‘Hello’, ‘,’, ‘world’, ‘’]。

将上述匹配模式中的\W*改成\W+,来看看效果:

>>> re.split('\W+','Hello,world')
['Hello', 'world']
>>> re.split('(\W+)','Hello,world')
['Hello', ',', 'world']
>>>

这个效果与老猿预想一致。在老猿预想的里面,使用“\W*”和“\W+”的区别应该就是在搜索文本头和尾的处理上二者有区别,“\W*”应该比“\W+”只多头和尾匹配的空字符串,毕竟二者都是贪婪模式,只是“\W*允许0次重复”。为什么执行结果却大相径庭呢?

经过仔细思考,老猿认为正则的匹配过程有关,在贪婪模式下,老猿理解上述正则表达式的匹配基本处理方法如下:

  1. 所有匹配过程都是从搜索文本当前匹配到的位置(为了后续方便称为当前匹配位置)开始的,首次匹配就从搜索文本位置0开始,其后真正匹配过程每匹配一个字符匹配位置加一(前视断言、后视断言等不消耗搜索文本的方法除外);
  2. 每次匹配时,都是从搜索文本当前匹配位置开始以类似切片的机制开始匹配:

    1)切片的开始位置为当前位置,切片的结束位置从当前位置开始逐一增加(假设当前位置为n,则第一次切片类似n:n,也就是空字符串);

    2)每次切片都会验证是否切片后的内容能否匹配当前模式,如果能匹配,切片结束位置加一,按此顺序处理,直到切片不能匹配为止;

    3)如果当前切片不能匹配,则匹配的搜索文本子串就是前一个切片(不妨称为匹配切片),如果前一个切片的起止位置相同则为空字符串,如果起始位置大于结束位置则没有匹配到,否则就是正常匹配;

    4)匹配到空串或正常子串都认为匹配成功,当前匹配位置=匹配切片结束位置+1。

这样我们回头来看使用“\W*”和“\W+”来匹配单词“Hello”的过程,由于每个字符当前位置的0长切片都为空字符串,他们满足“\W*”匹配要求,而下个长度为1的切片是字母字符,不能满足匹配的要求,因此会认为单词的每个字母之间都会被空字符串分割,如果不接受这样的结果,使用”\W+”来匹配就可以。

关于阅读本文所需要使用的基础知识请参考:

1、关于“\W*”和“\W+”的含义请参考《第11.15节 Python正则表达式转义符定义的特殊序列》;

2、关于切片请参考《第3章 Python的数据类型 第3.1节 功能强大的 Python序列概述》;

3、关于正则表达式贪婪模式请参考:《第11.9节 Python正则表达式的贪婪模式和非贪婪模式》及《转:正则表达式之 贪婪与非贪婪模式详解》;

4、关于re.split请参考《第11.22节Python 中re模块的split函数》。

老猿Python,跟老猿学Python!

博客地址:https://blog.csdn.net/LaoYuanPython


请大家多多支持,点赞、评论和加关注!谢谢!

Python正则表达式\W+和\W*匹配过程的深入分析的更多相关文章

  1. Python正则表达式处理中的匹配对象是什么?

    老猿才开始学习正则表达式处理时,对于搜索返回的匹配对象这个名词不是很理解,因此在前阶段<第11.3节 Python正则表达式搜索支持函数search.match.fullmatch.findal ...

  2. 第11.6节 Python正则表达式的字符串开头匹配模式及元字符“^”(插入符、脱字符)功能介绍

    符号"^"为插入符,也称为脱字符,在Python中脱字符表示匹配字符串的开头,即字符串的开头满足匹配模式的要求.这个功能有点类似搜索函数match,只是这是通过搜索模式来指定,而m ...

  3. 第11.5节 Python正则表达式搜索任意字符匹配及元字符“.”(点)功能介绍

    在re模块中,任意字符匹配使用"."(点)来表示, 在默认模式下,点匹配除了换行的任意字符.如果指定了搜索标记re.DOTALL ,它将匹配包括换行符的任意字符.关于搜索标记的含义 ...

  4. 第11.7节 Python正则表达式的字符串结尾匹配模式及元字符“$”功能介绍

    符号"$"表示匹配字符串的结尾,即字符串的结尾满足匹配模式的要求. 在 MULTILINE 模式(搜索标记中包含re.MULTILINE,关于搜索标记的含义请见<第11.2节 ...

  5. python 正则表达式替换字符串中匹配的字符

    import re street = '21 Ramkrishna Road' print(re.sub('Road$', 'Rd.', street)) 将结尾的Road用Rd.替换

  6. Python正则表达式书写容易碰到的陷阱:\W*和\W*?匹配过程遇到的问题

    老猿在分析<Python正则表达式\W+和\W*匹配过程的深入分析>中的问题时,想到一个问题,如果"re.split('(\W*)','Hello,world')"的处 ...

  7. Python正则表达式re.findall("[A-Za-z]([A-Za-z0-9])*[.]txt",'Abc2019.txt')的结果为什么是['9']

    在<Python妙用re.sub分析正则表达式匹配过程>中老猿分析了findall函数的返回情况,老猿前一阵子在执行这个语句时: >>> re.findall(" ...

  8. Python正则表达式re模块学习遇到的问题

    Python正则表达式处理的组是什么? Python正则表达式处理中的匹配对象是什么? Python匹配对象的groups.groupdict和group之间的关系 Python正则表达式re.mat ...

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

    Python正则表达式如何进行字符串替换实例 Python正则表达式在使用中会经常应用到字符串替换的代码.有很多人都不知道如何解决这个问题,下面的代码就告诉你其实这个问题无比的简单,希望你有所收获. ...

随机推荐

  1. leetcode37:path-sum-ii

    题目描述 给定一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum的路径, 例如: 给出如下的二叉树,sum=22,     5     / \   4  8   /    / ...

  2. 【实战分享】从选型到项目落地,漫谈 gRPC

    什么是 gRPC? gRPC 的几种常见模式 在学习 gRPC 的时候,相信大家对于它的四种模式都有了解,我们来简单回顾一下: 简单模式(Simple RPC):这种模式最为传统,即客户端发起一次请求 ...

  3. 01 . Vue简介,原理,环境安装

    简介 vue是一个JavaMVVM库,是一套用于构建用户界面的渐进式框架,是初创项目的首选前端框架.它是以数据驱动和组件化的思想构建的,采用自底向上增量开发的设计.它是轻量级的,它有很多独立的功能或库 ...

  4. 第05组 Alpha冲刺 (3/6)

    .th1 { font-family: 黑体; font-size: 25px; color: rgba(0, 0, 255, 1) } #ka { margin-top: 50px } .aaa11 ...

  5. MFC窗口通过OpenCV显示图片

    思路非常讨巧,就是将namedWindow创建的窗口的客户区贴到MFC的图片控件里面去,然后将剩下的窗口框架隐藏掉,代码如下: cv::Mat img = cv::imread("./tes ...

  6. shell编程之俄罗斯方块

    按键获取: 向上  ^[[A 向下  ^[[B 向左  ^[[D 向右  ^[[C 其中  ^[为ESC键. 按键获取的具体shell代码如下所示: #! /bin/bash GetKey() { a ...

  7. .net core中的哪些过滤器 (Authorization篇)

    前言 咱们上篇说到,过滤的简单介绍,但是未介绍如何使用,接下来几篇,我来给大家讲讲如何使用,今天第一篇是Authorization.认证过滤器, 开发环境介绍 开发工具:VS2019 开发环境:.ne ...

  8. JAVA 去除字符串前后的指定字符

    为了显示效果更好,我们可以将多余的字符去掉,代码如下: /** *去掉字符串前后的指定字符 */ public static String trimBothChars(String str, Stri ...

  9. nginx状态监控统计

    nginx是一款很优秀的web服务器软件,很多地方都有接触和使用到他,大部分的场景压力还没达到需要调优的地步,而调优的难点其实不在于调,而在于各项状态的监控,能够很快的找到资源在什么时候出现问题,调整 ...

  10. 内存使用过高点检checklist

    正在运行的程序按照内存段来组织,内存段的类型有如下几种: 代码段:用户程序指令,长期存在内存中 数据段:全局变量等,长期存在内存中 堆:局部变量,参数参数等,短期存在内存中 栈:动态存储,可变 代码段 ...