python | 探寻python正则表达式-1

简介: python | 探寻python正则表达式-1

image.png

面试官: 现在有一个需求,我们需要分析一个文本中的所有数据,需要抓出其中的所有人的电话号码,以 xxx-xxxx-xxxx 或者是 xxx-xxxxxxxx 或者是 xxxxxxxxxxx 为格式,请用python来编写一个程序来实现。


我: 使用re模块,额。。。。。,我知道,又没了。

这边文章,我们将介绍python正则表达式工具re,当然了,还是要说明一下python使用环境为: Python 3.6.8

image.png

什么是正则表达式


正则表达式定义


正则表达式(regex) 是描述文本模式的一种表达式,由模式字符串特殊字符组成,用于匹配、搜索、替换等等。



阐述模式和特殊字符


好了,正则表达式就介绍完了,咋的?还不明白啊。其实我刚开始看到时候,也不明白,我们举个小栗子来介绍一下模式和特殊字符吧。


假设有一个正则表达式是 abcdef,那么它的模式字符串就是abcdef,特殊字符没有。


假设还有一个正则表达式是^juejin.*pdudo$,在此正则表达式中:


  • ^ 是特殊字符,表示匹配字符串的开头。
  • juejin 是一个模式字符串,表示需要匹配的字面字符串。
  • .是一种特殊语法,. 表示匹配任意一个字符,* 表示重复前面的字符零次或多次。因此,".*" 表示匹配任意长度的字符串。
  • pdudo 是一个模式字符串,表示需要匹配的字面字符串。
  • $ 是特殊字符,表示匹配字符串的结尾。



python提供的特殊字符有哪些


额,这里又有一个问题了,你知道特殊字符有哪些么?


由于我们使用python来写正则,所以我们直接看python文档就可以了,例如:docs.python.org/zh-cn/3.7/l…


我们找到关于特殊字符的描述就可以了,例如:

image.png


这里就不原班搬运了。

python中,我们一般通过标准库re来编写正则表达式,接下来,我们一起来看看吧。



为什么要使用正则表达式


在介绍这个段落内容之前,我们不妨写个小功能,我们想要搜寻目录下文本的内容,内容必须包含pdudo


由于码上掘金不太好写文件之类的,所以我们给抽离出来定义为列表的形式。


大概内容如下:

image.png


使用暴力搜索法来搜索特定字符串

我们想搜索上述案例中,关于pdudo的字符串,先尝试一种不用正则表达式的方式。这个很简单,我们直接使用in关键字就可以完成,来看代码:


def main() -> None:
    testTxt = [
        ["今天,小狗pdduo迷路了。好心的主人找了很久也没找到它,心急如焚。终于,在一个角落里发现了它。小狗抬起头,看着主人,高兴地摇了摇尾巴,似乎在说:“谢谢你救了我。"],
        ["教室里传来一阵阵笑声,原来是pdudo调皮捣蛋。老师生气地走过去,pdudo马上低下了头。可当老师转过身时,pdudo又偷偷地对同桌saying:“快看,我藏起来了!"],
        ["爷爷退休后,经常给家里打电话聊天。他总是说:“最近有一个新朋友叫puddo,跟我聊得很开心。”后来才知道,那是他认识的一位年轻的志愿者,每周会给他打电话陪他聊天。"],
        ["在海滩上散步时,我们捡到了一个漂亮的贝壳,上面写着“pdduo”。这让我们想起了一个童话故事,于是我们决定将它带回家,留作纪念。"],
        ["昨天晚上,我在电视上看到了一个关于puddo的纪录片。它讲述了一只顽皮的小熊,经过几年的努力和奋斗,终于成为了丛林之王。这个故事让我想起了自己的梦想,也让我更加坚定要努力实现它。"]
    ]
    strs = "pdudo"
    for i in testTxt:
        if strs in i[0]:
            print(i)
if __name__ == '__main__':
    main()



还是很简单嘛,但是现在问题来了,如果要匹配以p开头以d结尾,匹配的字符串为5个字符,这个如果硬写,应该怎么写呢?


额,这个要写,也难不倒,对吧? 我们可以遍历一下。

逻辑为: 如果找到p字符,确定下标,再根据下标+4判断是否是字符d,如果是就输出,对吧?来写下:

strs = "pdudo"
for i in testTxt:
    j = 0
    while j < len(i[0]):
        if strs[0] == i[0][j] :
            if (j+4 < len(i[0])) and i[0][j+len(strs)-1] == strs[len(strs)-1]:
                print("search ok,pdudo中的p下标为: ",j,"原字符串为:",i[0])
                break
        j = j + 1

上述代码,就是用最原始的方法,遍历所有字符,如果找到了p则再判断该字符后4个字符位置是否是o,如果是则将p的下标和整段话都打印出来。

详细代码,可以看这里:


def main() -> None:
    testTxt = [
        ["今天,小狗pdduo迷路了。好心的主人找了很久也没找到它,心急如焚。终于,在一个角落里发现了它。小狗抬起头,看着主人,高兴地摇了摇尾巴,似乎在说:“谢谢你救了我。"],
        ["教室里传来一阵阵笑声,原来是pdudo调皮捣蛋。老师生气地走过去,pdudo马上低下了头。可当老师转过身时,pdudo又偷偷地对同桌saying:“快看,我藏起来了!"],
        ["爷爷退休后,经常给家里打电话聊天。他总是说:“最近有一个新朋友叫puddo,跟我聊得很开心。”后来才知道,那是他认识的一位年轻的志愿者,每周会给他打电话陪他聊天。"],
        ["在海滩上散步时,我们捡到了一个漂亮的贝壳,上面写着“pdduo”。这让我们想起了一个童话故事,于是我们决定将它带回家,留作纪念。"],
        ["昨天晚上,我在电视上看到了一个关于puddo的纪录片。它讲述了一只顽皮的小熊,经过几年的努力和奋斗,终于成为了丛林之王。这个故事让我想起了自己的梦想,也让我更加坚定要努力实现它。"]
    ]
    strs = "pdudo"
    for i in testTxt:
        j = 0
        while j < len(i[0]):
            if strs[0] == i[0][j] :
                if (j+4 < len(i[0])) and i[0][j+len(strs)-1] == strs[len(strs)-1]:
                    print("search ok,pdudo中的p下标为: ",j,"原字符串为:",i[0])
                    break
            j = j + 1
if __name__ == '__main__':
    main()


上面案例实现起来多很难吧,如果再上一层台阶,匹配字符串,必须是p在前和d灾后,中间的字符串必须由udo来组成,是不是更加头大了啊,这个时候,正则表达式就很好做这个事情。



使用正则表达式来匹配字符串

我们使用正则表达式,仅需定义一个匹配模式,而后无脑调用findall即可,例如查询可以这样写:


pattern = "p[duo]{3}o"
for i in testTxt:
    if re.findall(pattern, i[0]):
        print(i)

其中,p[duo]{3}o代表以p在前,以o在后,中间必须包含3个字符,字符局限于duo之间。

使用的时候,可以使用python标准库re,调用方法findall,参数为匹配模式 和 需要匹配的字符串即可。


可以看代码实现:

import re
def main() -> None:
    testTxt = [
        ["今天,小狗pdduo迷路了。好心的主人找了很久也没找到它,心急如焚。终于,在一个角落里发现了它。小狗抬起头,看着主人,高兴地摇了摇尾巴,似乎在说:“谢谢你救了我。"],
        ["教室里传来一阵阵笑声,原来是pdudo调皮捣蛋。老师生气地走过去,pdudo马上低下了头。可当老师转过身时,pdudo又偷偷地对同桌saying:“快看,我藏起来了!"],
        ["爷爷退休后,经常给家里打电话聊天。他总是说:“最近有一个新朋友叫puddo,跟我聊得很开心。”后来才知道,那是他认识的一位年轻的志愿者,每周会给他打电话陪他聊天。"],
        ["在海滩上散步时,我们捡到了一个漂亮的贝壳,上面写着“pdduo”。这让我们想起了一个童话故事,于是我们决定将它带回家,留作纪念。"],
        ["昨天晚上,我在电视上看到了一个关于puddo的纪录片。它讲述了一只顽皮的小熊,经过几年的努力和奋斗,终于成为了丛林之王。这个故事让我想起了自己的梦想,也让我更加坚定要努力实现它。"]
    ]
    pattern = "p[duo]{3}o"
    for i in testTxt:
        if re.findall(pattern, i[0]):
            print(i)
if __name__ == '__main__':
    main()

使用标准库re,很容易理解这个事情的。



正则表达式案例


还记得文章最开始的时候,我们需要写一个程序,以此来搜索以 xxx-xxxx-xxxx 或者是 xxx-xxxxxxxx 或者是 xxxxxxxxxxx 为格式的电话号码么? 我们了解了上述正则表达式后的写法后,应该会写了吧,我们来试试看:


我们构建了一份假的富婆通讯录,内容如下:

image.png

我们将其放置到列表中,我们想搜索一下这3种电话号码,分别为: xxx-xxxx-xxxx 、 xxx-xxxxxxxx 、 xxxxxxxxxxx ,就目前而言我们知晓手机号均为1开头,而后全是数字。所以如上三种方法,正则表达式可以这样写:

字符串 正则表达式
xxx-xxxx-xxxx 1[0-9]{2}-[0-9]{4}-[0-9]{4}
xxx-xxxxxxxx 1[0-9]{2}-[0-9]{8}
xxxxxxxxxxx 1[0-9]{10}

其中正则表达式的 [] 代表合集,即: [abc]可以匹配abc的其中一个,而后面的{n}则可以匹配前面[]中数字n次。


拿这个举例,模式 和 特殊字符,我们分别用 蓝色 和 红色 标注出来一下:


image.png

如果不明白的,我可以滑到最上面去看看。

但是我们需要匹配3个,我们如何用一个正则表达式来编写呢?答案是可以使用竖线分割|,于是乎,正则表达式就成了这样的了: 1[0-9]{2}-[0-9]{4}-[0-9]{4}|1[0-9]{2}-[0-9]{8}|1[0-9]{10}

最后使用re调用findall就可以了。


import re
def main() -> None:
    testTxt = [
        ["姓名: 张X 女 英文名: Emily 北京市海淀区中关村大街X号 138-1234-5678 爱好: 游泳 职业: 律师"],
        ["姓名: 李X英 性别: 女 英文名: Olivia 地址: 成都市高新区天府大道中段XXX号 电话号码: 156-12345678 健身 职业: 医生"],
        ["姓名: 赵X华 女 英文名: James 武汉市江汉区解放大道XX号 15812345678 摄影 职业: 教育工作者"]
    ]
    pattern = "1[0-9]{2}-[0-9]{4}-[0-9]{4}|1[0-9]{2}-[0-9]{8}|1[0-9]{10}"
    for i in testTxt:
        print(re.findall(pattern,i[0]))
if __name__ == '__main__':
    main()

如果我们我们还想将名字和职业以及电话号码串起来呢? 我们可以定义3个正则表达式,分别是电话、姓名以及职业:

telPattern = "1[0-9]{2}-[0-9]{4}-[0-9]{4}|1[0-9]{2}-[0-9]{8}|1[0-9]{10}"
namePattern = "姓名: .*? "
jobPattern = "职业: .*?$"

我们改改代码,就可以实现了:

image.png

关于更多的正则表达式,可以查看上述提供的文档,也可以看下一篇博客。



总结


该篇文章,先是介绍了正则表达式,而后解释了正则表达式中的模式和特殊字符,最后对比了一下使用正则表达式和不是用正则表达式的区别。最后的最后,提供了一个正则表达式搜索电话号码的案例。


特别是python文档上的特殊字符,应该好好了解下。

后面,python使用正则表达式,只能使用re.findall么? 我们后面会详细介绍python re


相关文章
|
1月前
|
数据库 Python
Python网络数据抓取(8):正则表达式
Python网络数据抓取(8):正则表达式
19 2
|
24天前
|
自然语言处理 JavaScript 前端开发
Python高级语法与正则表达式(二)
正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
|
24天前
|
安全 算法 Python
Python高级语法与正则表达式(一)
Python提供了 with 语句的写法,既简单又安全。 文件操作的时候使用with语句可以自动调用关闭文件操作,即使出现异常也会自动关闭文件操作。
|
1月前
|
Python
Python使用正则表达式分割字符串
在Python中,你可以使用re模块的split()函数来根据正则表达式分割字符串。这个函数的工作原理类似于Python内置的str.split()方法,但它允许你使用正则表达式作为分隔符。
|
18天前
|
Python
Python正则表达式详解:掌握文本匹配的魔法
Python正则表达式详解:掌握文本匹配的魔法
|
18天前
|
Python
python re 正则表达式库的使用
python re 正则表达式库的使用
11 0
|
26天前
|
Python
python正则表达式入门
python正则表达式入门
|
1月前
|
SQL 算法 数据挖掘
leetCode第十题 : 正则表达式匹配 动态规划【10/1000 python】
leetCode第十题 : 正则表达式匹配 动态规划【10/1000 python】
|
1月前
|
数据采集 监控 Python
Python新手必看:正则表达式入门到精通只需这一篇!
了解 Python 中的正则表达式,用于高效处理字符串。导入 `re` 模块,用 `r` 前缀避免转义困扰。示例:`re.split` 切分字符串,`re.findall` 进行匹配与查找,数量词如 `*`, `+`, `?` 控制匹配次数,边界匹配定位开始或结束。使用 `group` 和 `sub` 进行组合操作,解决复杂文本处理问题。正则表达式是字符串处理的利器,助你轻松应对各种场景。
17 0
|
1月前
|
数据库 C++ 索引
Python 正则表达式
Python 正则表达式