199|6

4866

帖子

5

TA的资源

版主

 

《Python编程快速上手》7、正则表达式 [复制链接]

        正则表达式是一种匹配的方式,我们在进行多位字符查找是可能会通过不断的遍历比较进行对比,如果样本比较大可能需要非常多的次数进行判断,正则表达式的存在可以大大简化这个过程。
        正则表达式,简称为 regex,是文本模式的描述方法。例如,\d 是一个正则表达式,表示一位数字字符,即任何一位 0 到 9 的数字。Python 使用正则表达式 \d\d\d-\d\d\d-\d\d\d\d,来匹配前面 isPhoneNumber() 函数匹配的同样文本:3 个数字、一个短横线、3 个数字、一个短横线、4 个数字。所有其他字符串都不能匹配 \d\d\d-\d\d\d-\d\d\d\d 正则表达式。当然了正则表达式可以复杂得多。例如,在一个模式后加上花括号包围的 3({3}),就是说,“匹配这个模式 3 次”。所以较短的正则表达式 \d{3}-\d{3}-\d{4},也匹配正确的电话号码格式。
        Python 中所有正则表达式的函数都在 re 模块中,对于3.x版本的存储在 regex模块中:
                向 regex.compile() 传入一个字符串值,表示正则表达式,它将返回一个 Regex 模式对象(或者就简称为 Regex 对象);
                search 方法只匹配第一次,返回一个 Match 对象;
                findall() 方法匹配所有,返回一个字符串列表;
        本次加载import regex提示Unused import statement 'import regex',而且import regex为灰色,解决办法是通过Pycharm file 菜单下有Invalidate caches/Restart菜单栏,点击清除缓存重新启动Pycharm即可。
        本书用一个查找电话号码的例子让我们对其进行进一步体验比较:
import regex
def is_phone_number(text):
if len(text) != 12:
return False
for i in range(0, 3):
if not text[i].isdecimal():
return False
if text[3] != '-':
return False
for i in range(4, 7):
if not text[i].isdecimal():
return False
if text[7] != '-':
return False
for i in range(8, 12):
if not text[i].isdecimal():
return False
return True
message = 'Call me at 415-555-1011 tomorrow. 415-566-9999 is my office.'
a = 0
for a in range(len(message)):
chunk = message[a:a+12]
if is_phone_number(chunk):
print('Phone number found: ' + chunk)
print(a)
print('-------------')
phoneNumRegex = regex.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
ob = phoneNumRegex.search(message)
print('First Phone number found: ' + ob.group())
print('-------------')
a = 0
obs = phoneNumRegex.findall(message)
for a in range(len(obs)):
chunk = obs[a]
print('Phone number found: ' + chunk)
print(a+1)
print('-------------')

结果如下:

image.png
有一些小技巧:
        使用括号可以分组,注意不要超过括号的数量,group(1) 对应第一个括号,group(0) 匹配全部;
        (使用括号分组后)使用groups()返回的是一个元组第一次匹配的,元组可以使用多重复制的技巧;findall()返回的列表元素也是元组;
        字符 | 称为“管道”,希望匹配许多表达式中的一个,返回第一个匹配成功的,例如A|B,首先和A匹配符合就不与B匹配了
import regex
message = 'Call me at 415-555-1011 tomorrow. 415-566-9999 is my office.'
phoneNumRegex = regex.compile(r'(\d\d\d)-\d\d\d-\d\d\d\d')
ob = phoneNumRegex.search(message)
print('First Phone number found: ' + ob.group())
print('-------------')
phoneNumRegex = regex.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
ob = phoneNumRegex.search(message)
print('First Phone number found: ' + ob.group(2))
print(ob.groups())
obs = phoneNumRegex.findall(message)
print(obs)
print('-------------')
phoneNumRegex = regex.compile(r'\d\d\d\d|\d\d\d')
ob = phoneNumRegex.search(message)
print('First Phone number found: ' + ob.group())
obs = phoneNumRegex.findall(message)
print(obs)

结果如下:

212906pztlunuallltxskh.png

        后面使用控制台进行验证,发现比程序要好用

        字符?表明它前面的分组在这个模式中是可选的:
batRegex = regex.compile(r'Bat(wo)?man')
mo1 = batRegex.search('The Adventures of Batman')
mo1.group()
'Batman'
mo1.groups()
(None,)
mo1 = batRegex.findall('The Adventures of Batman')
findall
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'findall' is not defined
mo1
['']
mo2 = batRegex.search('The Adventures of Batwoman')
mo2.group()
'Batwoman'
mo3 = batRegex.search('The Adventures of Batman Batwoman')
mo3.group()
'Batwoman'

        由上可见groups()和findall()方法不能用,返回的是空,加问号后如果有提前遍历返回;

        *(称为星号)意味着“匹配零次或多次”,即星号之前的分组,可以在文本中出现任意次。它可以完全不存在,或一次又一次地重复。+ 则意味着“匹配一次或多次”。星号不要求分组出现在匹配的字符串中,但加号不同,加号前面的分组必须“至少出现一次”。这不是可选的。
        如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括号包围的数字。例如,正则表达式 (Ha){3} 将匹配字符串 'HaHaHa',但不会匹配 'HaHa',因为后者只重复了 (Ha) 分组两次。可以不写花括号中的第一个或第二个数字,不限定最小值或最大值。例如,(Ha){3,} 将匹配 3 次或更多次实例,(Ha){,5} 将匹配 0 到 5 次实例。Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽可能匹配最长的字符串。花括号的“非贪心”版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。
缩写字符分类如下:
212906zvvrnij9vi9ibiwv.png

        方括号定义自己的字符分类,例如[aeiouAEIOU] 将匹配所有元音字符;

        插入符号 ^ ,表明匹配必须发生在被查找文本开始处。类似地,可以再正则表达式的末尾加上美元符号 $ ,表示该字符串必须以这个正则表达式的模式结束;
        . 字符称为“通配符”。它匹配除了换行之外的所有字符;
        可以用 .* 表示“任意文本”。回忆一下,句点字符表示“除换行外所有单个字符”,星号字符表示“前面字符出现零次或多次”。
 
        正则表达式不仅能找到文本模式,而且能够用新的文本替换掉这些模式。Regex 对象的 sub() 方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式;
        向 re.compile() 传入变量 re.VERBOSE,作为第二个参数,可以忽略正则表达式字符串中的空白符和注释;
        向 re.compile() 传入变量re.IGNORECASE作为第二个参数,来忽略大小写;第二参数可以通过“按位或”操作符同时起作用;

最新回复

很详细  详情 回复 发表于 6 天前
 
 

回复
举报

6300

帖子

8

TA的资源

版主

 

正则表达式不仅能找到文本模式,而且能够用新的文本替换掉这些模式。Regex 对象的 sub() 方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式;

        向 re.compile() 传入变量 re.VERBOSE,作为第二个参数,可以忽略正则表达式字符串中的空白符和注释;

        向 re.compile() 传入变量re.IGNORECASE作为第二个参数,来忽略大小写;第二参数可以通过“按位或”操作符同时起作用;

我现在对正则还是没有学习好,恭喜版主大佬喜得这么好的读书机会。

点评

从这节开始,难度直接拉上去了,各种使用技巧,根本记不过来啊   详情 回复 发表于 7 天前
 
 
 

回复

4866

帖子

5

TA的资源

版主

 
lugl4313820 发表于 2024-5-16 07:38 正则表达式不仅能找到文本模式,而且能够用新的文本替换掉这些模式。Regex 对象的 sub() 方法需要传入两个 ...

从这节开始,难度直接拉上去了,各种使用技巧,根本记不过来啊 

 
 
 

回复

131

帖子

0

TA的资源

一粒金砂(高级)

 

通过示例去测试可以大大加深印象,而且直观

 
 
 

回复

382

帖子

1

TA的资源

纯净的硅(初级)

 

是不是有那种RegEx的手册,专门讲字符模式的?

当然必须实践才可以熟能生巧。。。。。

点评

我也不是很懂,作为初学者安装这些三方固件都是各种问题呢  详情 回复 发表于 7 天前
 
 
 

回复

4866

帖子

5

TA的资源

版主

 
hellokitty_bean 发表于 2024-5-16 13:44 是不是有那种RegEx的手册,专门讲字符模式的? 当然必须实践才可以熟能生巧。。。。。

我也不是很懂,作为初学者安装这些三方固件都是各种问题呢

 
 
 

回复

106

帖子

0

TA的资源

一粒金砂(中级)

 

很详细


 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表