python王者归来—学习笔记(20)

2023-11-01

继续第十六章 正则表达式

一、正则表达式特殊字符。我们知道\d代表的是数字字符,也就是从0-9的阿拉伯数字,如果使用管道|的观念,\d相当于是下列正则表达式:(0|1|2|3|4|5|6|7|8|9)。正则表达式的特殊字符说明如下:

import re

msg = 'John, Johnson, Johnnason and Johnnathan will attend my party tonight.'
pattern = '\w+' #不限长度的单词
txt = re.findall(pattern, msg)  #英文单词分离
print(txt)

pattern = 'John\w+' #John开头的单词
txt = re.findall(pattern, msg)
print(txt)

msg = '1 cat, 2 dogs, 3 pigs, 4 swans'
#\d+: 不限长度数字 \s: 空格  \w+: 不限长度的数字字母和下划线字符连续字符
pattern = '\d+\s\w+'
txt = re.findall(pattern, msg)
print(txt)

二、字符分类。Python可以使用中括号来设定字符,可参考下列范例。[a-z]:代表a-z的小写字符。[A-Z]:代表A-Z的大写字符。[aeiouAEIOU]:代表英文发音的元音字符。[2-5]:代表2-5的数字。在字符分类中,中括号内可以不用放上正则表示法的反斜杠\执行.、?、*、(、)等字符的转义。例如,[2-5.]会搜寻2-5的数字和句点,这个语法不用写成[2-5\.]。如果在中括号内的左方加上^字符,意义是搜寻不在这些字符内的所有字符

import re

msg = '1. cat, 2. dogs, 3. pigs, 4. swans'
pattern = '[2-5.]'  #查找2-5的数字和句点
txt = re.findall(pattern, msg)
print(txt)

pattern = '[^2-5.]'  #查找不是2-5的数字和句点的字符
txt = re.findall(pattern, msg)
print(txt)

^字符除了用在中括号内左侧表示反义之外,在正则表达式中起始位置加上^字符,表示正则表示法的字符串必须出现在被查找字符串的起始位置,这样查找成功才算成功。正则表达式的末端放置$字符时,表示正则表达式的字符串必须出现在被查找字符串的最后位置,这样查找成功才算成功。我们也可以将^字符和$字符混合使用,这时如果既要符合开始字符串也要符合结束字符串,所以被搜寻的句子一定要只有一个字符串

import re

msg = 'John will attend my party tonight.'
pattern = '^John' #以John开头的字符
txt = re.findall(pattern, msg)  
print(txt)

pattern = '\W$'   #结尾字符是非英文字母数字和下划线字符
txt = re.findall(pattern, msg)  
print(txt)

msg = 'My best friend is John, He is 28'
pattern = '^John'  #以John开头的字符
txt = re.findall(pattern, msg)
print(txt)

pattern = '\d$'    #结尾字符是数字字符
txt = re.findall(pattern, msg)
print(txt)

msg = '09238423793'
pattern = '^\d+$'  #开头和结尾都是数字的字符串
txt = re.findall(pattern, msg)
print(txt)

msg = '09238ese3793'
pattern = '^\d+$'  #开头和结尾都是数字的字符串
txt = re.findall(pattern, msg)
print(txt)

单一字符通配符(wildcard)“.”表示可以查找除了换行字符以外的所有字符(包含空白字符),但是只限定一个字符,如果搜寻的是真正的“.”字符,须使用反斜杠“\.”。

所有字符使用通配符“.*”,它将“.”字符与“*”组合,表示可以查找所有字符,意义是查找0到多个通配符(换行字符除外)。

使用“.*”查找时碰上换行字符,查找就停止。Python的re模块提供参数re.DOTALL,功能是包含查找换行字符,可以将此参数放在search( )、findall( )或compile( )

import re

msg = 'cat hat at matter flat'
pattern = '.at' #单一字符通配符.
txt = re.findall(pattern, msg)
#第3个at符合,Python自动加上空格符。第5个由于只能加上一个字符,所以结果是lat
print(txt)

msg = 'Name: Jiin-Kwei Hung Address: 8F, Nan-Jing E.Rd'
pattern = 'Name:(.*) Address:(.*)' #所有字符通配符.*
txt = re.search(pattern, msg)
name, address = txt.groups()
print("Name: ", name)
print("Address:", address)


msg = 'Name: Jiin-Kwei Hung \nAddress: 8F, Nan-Jing E.Rd'
pattern = '.*'
txt = re.search(pattern, msg) #查找到换行符终止
print(txt.group())

txt = re.search(pattern, msg, re.DOTALL) #查找包含换行符re.DOTALL
print(txt.group())

三、MatchObject对象。之前已经讲解了查找字符串中最重要的2个方法re.search( )和re.findall( )。这里再讲解MatchObject几个重要的方法(method)。首先是re模块的另一个方法re.match( ),这个方法其实和re.search( )相同,差异是re.match( )只查找比对字符串开始的字,如果失败就算失败。re.search( )则是查找整个字符串。至于re.match( )查找成功会传回MatchObject对象,若是查找失败会传回None,这部分与re.search( )相同:

import re

msg1 = 'John will attend my party tonight.'
msg2 = 'My best friend is John.'
pattern = 'John'
txtmatch1 = re.match(pattern, msg1) #msg1中John子串在开头,所以用match查找不到
txtmatch2 = re.match(pattern, msg2) #msg2中John子串不在开头,所以用match查找不到
print(txtmatch1) #打印MatchObject对象
print(txtmatch1.group()) #打印匹配字符串
print(txtmatch2) #打印None

print("查找成功字符串起始索引位置:", txtmatch1.start())
print("查找成功字符串结束索引位置:", txtmatch1.end())
print("查找成功字符串起始结束索引位置:", txtmatch1.span())

txtsearch1 = re.search(pattern, msg1)
txtsearch2 = re.search(pattern, msg2)
print(txtsearch1) #打印MatchObject对象
print(txtsearch1.group()) #打印匹配字符串
print(txtsearch2) #打印MatchObject对象
print(txtsearch2.group()) #打印匹配字符串

print("查找成功字符串起始索引位置:", txtsearch1.start())
print("查找成功字符串结束索引位置:", txtsearch1.end())
print("查找成功字符串起始结束索引位置:", txtsearch1.span())

从上面程序运行结果可知,当使用re.match( )和re.search( )都查找成功时,两者的MatchObject对象内容是相同的。span是注明成功查找字符串的起始位置和结束位置,这里起始索引位置是0,结束索引位置是4。match则是注明成功查找的字符串内容。Python提供下列取得MatchObject对象内容的重要方法:group():返回查找到的字符串。start():返回查找到的字符串的起始位置。 end():返回查找到的字符串的结束位置。span():返回查找到的字符串的起始结束位置。

re模块内的sub( )方法可以用新的字符串取代原本字符串的内容,基本使用语法如下:result = re.sub(pattern, newstr, msg)。pattern是查找的字符串,如果查找成功则用newstr取代,同时成功取代的结果返回给result变量,如果查找到多个相同字符串,这些字符串将全部被取代,需留意原先msg内容将不会改变。如果查找失败则将msg内容返回给result变量,当然msg内容也不会改变,这里举一个用正则表达式re.sub()方法隐藏真实姓名的例子:

import re

msg = 'CIA Mark told CIA Linda that secret USB had given to CIA Peter.'
pattern = r'CIA (\w)\w*' #查找CIA + 空一格后的名字
newstr = r'\1***'    #新字符串只保留第一个字母
txt = re.sub(pattern, newstr, msg) #新字符串替代查找字符串
print("替代成功:", txt)

上述程序代码pattern中将查找CIA字符串外加空一格后出现不限长度的字符串(可以由英文大小写或数字或底线所组成)。括号内的(\w)代表必须只有一个字符,同时小括号代表这是一个分组(group),由于整行只有一个括号所以知道这是第一分组,同时只有一个分组,括号外的\w*表示可以有0到多个字符。所以(\w)\w*相当于是1-多个字符组成的单字,同时存在分组1。newstr中的\1代表用分组1找到的第一个字母当作字符串开头,后面***则是接在第一个字母后的字符。对CIA Mark而言所找到的第一个字母是M,所以取代的结果是M***。对CIALinda而言所找到的第一个字母是L,所以取代的结果是L***。对CIA Peter而言所找到的第一个字母是P,所以取代的结果是P***。

四、处理比较复杂的正则表达式。有一个正则表达式内容如下:

pattern = r((\d{3,4}|\(\d{3,4}\))?(\s|-)?\d{8}(\s*(ext|ext.)\s*\d{2,4})?)

我们可以使用3个单引号(或是双引号)将过长的字符串拆成多行表达,当我们适当地拆解后,可以为每一行加上批注,整个正则表达式就变得简单了:

import re

msg = '''020-88223349, (0591)-26669999, 025-29998888 ext 123,
         56781234, 027 33887766 ext. 1222'''

pattern = r'''(
    (\d{3,4}|\(\d{3,4}\))?        #区号
    (\s|-)?                       #区号与电话号码分隔符
    \d{8}                         #电话号码
    (\s*(ext|ext.)\s*\d{2,4})?    #2-4位的分机号码
    )'''

phoneNum = re.findall(pattern, msg, re.VERBOSE)
print(phoneNum)

使用Python时,如果想在正则表达式中加上批注,必须配合使用re.VERBOSE参数,然后将此参数放在search( )、findall( )或compile( ),否则pattern不生效。

下面再看一个电子邮件查找的例子。在字处理过程中,必须在文件内将电子邮件地址解析出来很常见:

import re

msg = '''txt@deeplearning.com.cn bsdfas@gmail.com'''

pattern = r'''(
    [a-zA-Z0-9_.]+         #邮箱账号
    @                      #区号与电话号码分隔符
    [a-zA-Z0-9-.]+         #主机域名domain
    [\.]                   #.符号
    [a-zA-Z]{2,4}          #可能是com或edu或其它
    ([\.])?                #.符号,也可能无,例如美国
    ([a-zA-Z]{2,4})?       #国别简称,也可能无
    )'''

phoneNum = re.findall(pattern, msg, re.VERBOSE)
print(phoneNum)

如果我们想要一次放置多个参数特性,方法是使用管道|概念,例如,可以使用下列方式:datastr = re.search(pattern, msg, re.IGNORECASE|re.DOTALL|re.VERBOSE)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python王者归来—学习笔记(20) 的相关文章

  • Spark 请求最大计数

    我是 Spark 的初学者 我尝试请求允许我检索最常访问的网页 我的要求如下 mostPopularWebPageDF logDF groupBy webPage agg functions count webPage alias cntW
  • Python中Decimal类型的澄清

    每个人都知道 或者至少 每个程序员都应该知道 http docs oracle com cd E19957 01 806 3568 ncg goldberg html 即使用float类型可能会导致精度错误 然而 在某些情况下 精确的解决方
  • Python - 将宽字符字符串从二进制文件转换为 Python unicode 字符串

    这是漫长的一天 我有点困惑 我正在读取一个包含大量宽字符字符串的二进制文件 我想将它们转储为 Python unicode 字符串 为了解压非字符串数据 我使用 struct 模块 但我不知道如何对字符串执行相同的操作 例如 阅读 系列 一
  • python future 和元组解包

    实现像使用 future 进行元组解包这样的事情的优雅 惯用的方法是什么 我有这样的代码 a b c f x y g a b z h y c 我想将其转换为使用期货 理想情况下我想写一些类似的东西 a b c ex submit f x y
  • Django 模型在模板中不可迭代

    我试图迭代模型以获取列表中的第一个图像 但它给了我错误 即模型不可迭代 以下是我的模型和模板的代码 我只需要获取与单个产品相关的列表中的第一个图像 模型 py class Product models Model title models
  • Argparse nargs="+" 正在吃位置参数

    这是我的解析器配置的一小部分 parser add argument infile help The file to be imported type argparse FileType r default sys stdin parser
  • 从零开始的 numpy 形状意味着什么

    好的 我发现数组的形状中可以包含 0 对于将 0 作为唯一维度的情况 这对我来说是有意义的 它是一个空数组 np zeros 0 但如果你有这样的情况 np zeros 0 100 让我很困惑 为什么这么定义呢 据我所知 这只是表达空数组的
  • 忽略 Mercurial hook 中的某些 Mercurial 命令

    我有一个像这样的善变钩子 hooks pretxncommit myhook python path to file myhook 代码如下所示 def myhook ui repo kwargs do some stuff 但在我的例子中
  • 如何创建一个语句来打印以特定单词开头的单词? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 python 中打印从特定字母开始的单词 而不使用函数 而是使用方法或循环 1 我有一个字符串 想要打印以 m 开头的单词 S
  • Pandas 数据帧到 numpy 数组 [重复]

    这个问题在这里已经有答案了 我对 Python 很陌生 经验也很少 我已经设法通过复制 粘贴和替换我拥有的数据来使一些代码正常工作 但是我一直在寻找如何从数据框中选择数据 但无法理解这些示例并替换我自己的数据 总体目标 如果有人真的可以帮助
  • 使用鼻子获取设置中当前测试的名称

    我目前正在使用鼻子编写一些功能测试 我正在测试的库操作目录结构 为了获得可重现的结果 我存储了一个测试目录结构的模板 并在执行测试之前创建该模板的副本 我在测试中执行此操作 setup功能 这确保了我在测试开始时始终具有明确定义的状态 现在
  • Numpy 过滤器平滑零区域

    我有一个 0 及更大整数的 2D numpy 数组 其中值代表区域标签 例如 array 9 9 9 0 0 0 0 1 1 1 9 9 9 9 0 7 1 1 1 1 9 9 9 9 0 2 2 1 1 1 9 9 9 8 0 2 2 1
  • 将 matplotlib 颜色图集中在特定值上

    我正在使用 matplotlib 颜色图 seismic 绘制绘图 并且希望白色以 0 为中心 当我在不进行任何更改的情况下运行脚本时 白色从 0 下降到 10 我尝试设置 vmin 50 vmax 50 但在这种情况下我完全失去了白色 关
  • 在 Pandas 中使用正则表达式的多种模式

    我是Python编程的初学者 我正在探索正则表达式 我正在尝试从 描述 列中提取一个单词 数据库名称 我无法给出多个正则表达式模式 请参阅下面的描述和代码 描述 Summary AD1 Low free DATA space in data
  • Python 将日志滚动到变量

    我有一个使用多线程并在服务器后台运行的应用程序 为了无需登录服务器即可监控应用程序 我决定包括Bottle http bottlepy org为了响应一些HTTP端点并报告状态 执行远程关闭等 我还想添加一种查阅日志文件的方法 我可以使用以
  • 限制 django 应用程序模型中的单个记录?

    我想使用模型来保存 django 应用程序的系统设置 因此 我想限制该模型 使其只能有一条记录 极限怎么办 尝试这个 class MyModel models Model onefield models CharField The fiel
  • Python 无法使用套接字绑定我的外部/公共 IP 地址,给出错误但是当使用本地 IP 地址时,错误不会显示

    这是出现主要错误的代码 与我的本地 IP 的绑定将起作用 s bind 192 168 1 4 port 与我的公共 IP 的绑定失败并出现以下错误 s bind 99 99 99 99 port WinError 10049 请求的地址在
  • 迭代 pandas 数据框的最快方法?

    如何运行数据框并仅返回满足特定条件的行 必须在之前的行和列上测试此条件 例如 1 2 3 4 1 1 1999 4 2 4 5 1 2 1999 5 2 3 3 1 3 1999 5 2 3 8 1 4 1999 6 4 2 6 1 5 1
  • 您可以使用关键字参数而不提供默认值吗?

    我习惯于在 Python 中使用这样的函数 方法定义 def my function arg1 None arg2 default do stuff here 如果我不供应arg1 or arg2 那么默认值None or default
  • Scrapy Spider不存储状态(持久状态)

    您好 有一个基本的蜘蛛 可以运行以获取给定域上的所有链接 我想确保它保持其状态 以便它可以从离开的位置恢复 我已按照给定的网址进行操作http doc scrapy org en latest topics jobs html http d

随机推荐