热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python中正则表达式的使用详解

这篇文章主要介绍了python中正则表达式的使用详解,另附上一些常用的Python正则例子,有需要的朋友可以参考下
从学习Python至今,发现很多时候是将Python作为一种工具。特别在文本处理方面,使用起来更是游刃有余。

说到文本处理,那么正则表达式必然是一个绝好的工具,它能将一些繁杂的字符搜索或者替换以非常简洁的方式完成。

我们在处理文本的时候,或是查询抓取,或是替换.

一.查找
如果你想自己实现这样的功能模块,输入某一个ip地址,得到这个ip地址所在地区的详细信息.

然后你发现http://ip138.com 可以查出很详细的数据

但是人家没有提供api供外部调用,但是我们可以通过代码模拟查询然后对结果进行抓取.

通过查看这个相应页面的源码,我们可以发现,结果是放在三个

  • 中的

    代码如下:

























    ip138.com IP查询(搜索IP地址的地理位置)

    您查询的IP:121.0.29.231

    • 本站主数据:浙江省杭州市 阿里巴巴
    • 参考数据一:浙江省杭州市 阿里巴巴
    • 参考数据二:浙江省杭州市 阿里巴巴
    如果您发现查询结果不详细或不正确,请使用IP数据库自助添加功能进行修正




    IP地址或者域名:

    如果你了解正则表达式你可能会写出

    正则表达式

    代码如下:


    (?<=

  • ).*?(?=
  • )

    这里使用了前瞻:lookahead 后顾: lookbehind,这样的好处就是匹配的结果中就不会包含html的li标签了.

    如果你对自己写的正则表达式不是很自信的话,可以在一些在线或者本地的正则测试工具进行一些测试,以确保正确.

    接下来的工作就是如果用Python实现这样的功能,首先我们得将正则表达式表示出来:

    代码如下:


    r"(?<=

  • ).*?(?=
  • )"

    Python中字符串前面加上前导r这个字符,代表这个字符串是R aw String(原始字符串),也就是说Python字符串本身不会对字符串中的字符进行转义.这是因为正则表达式也有转义字符之说,如果双重转义的话,易读性很差.

    这样的串在Python中我们把它叫做"regular expression pattern"

    如果我们对pattern进行编译的话

    代码如下:


    prog = re.compile(r"(?<=

  • ).*?(?=
  • )")

    我们便可以得到一个正则表达式对象regular expression object,通过这个对象我们可以进行相关操作.

    比如

    代码如下:


    result=prog.match(string)
    ##这个等同于
    result=re.match(r"(?<=

  • ).*?(?=
  • )",string)
    ##但是如果这个正则需要在程序匹配多次,那么通过正则表达式对象的方式效率会更高

    接下来就是查找了,假设我们的html结果已经以html的格式存放在text中,那么通过

    代码如下:


    result_list = re.findall(r"(?<=

  • ).*?(?=
  • )",text)

    便可以取得所需的结果列表.

    二.替换
    使用正则表达式进行替换非常的灵活.

    比如之前我在阅读Trac这个系统中wiki模块的源代码的时候,就发现其wiki语法的实现就是通过正则替换进行的.

    在使用替换的时候会涉及到正则表达式中的Group分组的概念.

    假设wiki语法中使用!表示转义字符即感叹号后面的功能性字符会原样输出,粗体的语法为

    写道
    '''这里显示为粗体'''
    那么有正则表达式为

    代码如下:


    r"(?P!?''')"

    这里的?P是Python正则语法中的一部分,表示其后的group的名字为"bold"

    下面是替换时的情景,其中sub函数的第一个参数是pattern,第二个参数可以是字符串也可以是函数,如果是字符串的话,那么就是将目标匹配的结果替换成指定的结果,而如果是函数,那么函数会接受一个match object的参数,并返回替换后的字符串,第三个参数便是源字符串.

    代码如下:


    result = re.sub(r"(?P!?''')", replace, line)

    每当匹配到一个三单引号,replace函数便运行一次,可能这时候需要一个全局变量记录当前的三单引号是开还是闭,以便添加相应的标记.

    在实际的trac wiki的实现的时候,便是这样通过一些标记变量,来记录某些语法标记的开闭,以决定replace函数的运行结果.

    --------------------

    示例

    一. 判断字符串是否是全部小写

    代码

    代码如下:


    # -*- coding: cp936 -*-
    import re
    s1 = 'adkkdk'
    s2 = 'abc123efg'

    an = re.search('^[a-z]+$', s1)
    if an:
    print 's1:', an.group(), '全为小写'
    else:
    print s1, "不全是小写!"

    an = re.match('[a-z]+$', s2)
    if an:
    print 's2:', an.group(), '全为小写'
    else:
    print s2, "不全是小写!"

    结果

    究其因

    1. 正则表达式不是python的一部分,利用时需要引用re模块

    2. 匹配的形式为: re.search(正则表达式, 带匹配字串)或re.match(正则表达式, 带匹配字串)。两者区别在于后者默认以开始符(^)开始。因此,

    re.search('^[a-z]+$', s1) 等价于 re.match('[a-z]+$', s2)
    3. 如果匹配失败,则an = re.search('^[a-z]+$', s1)返回None

    group用于把匹配结果分组

    例如

    代码如下:


    import re
    a = "123abc456"
    print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体
    print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123
    print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc
    print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456

    1)正则表达式中的三组括号把匹配结果分成三组

      group() 同group(0)就是匹配正则表达式整体结果

      group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。

    2)没有匹配成功的,re.search()返回None

    3)当然郑则表达式中没有括号,group(1)肯定不对了。

    二. 首字母缩写词扩充

    具体示例

    FEMA Federal Emergency Management Agency
    IRA Irish Republican Army
    DUP Democratic Unionist Party

    FDA Food and Drug Administration
    OLC Office of Legal Counsel
    分析

    缩写词  FEMA
    分解为  F*** E*** M*** A***
    规律   大写字母 + 小写(大于等于1个)+ 空格
    参考代码

    代码如下:


    import re
    def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr):
    ma += abbr[i] + "[a-z]+" + ' '
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
    return p.group()
    else:
    return ''

    print expand_abbr("Welcome to Algriculture Bank China", 'ABC')

    结果

    问题

    上面代码对于例子中的前3个是正确的,但是后面的两个就错了,因为大写字母开头的词语之间还夹杂着小写字母词

    规律

    大写字母 + 小写(大于等于1个)+ 空格 + [小写+空格](0次或1次)

    参考代码

    代码如下:


    import re
    def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr-1):
    ma += abbr[i] + "[a-z]+" + ' ' + '([a-z]+ )?'
    ma += abbr[lenabbr-1] + "[a-z]+"
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
    return p.group()
    else:
    return ''

    print expand_abbr("Welcome to Algriculture Bank of China", 'ABC')

    技巧

    中间的 小写字母集合+一个空格,看成一个整体,就加个括号。要么同时有,要么同时没有,这样需要用到?,匹配前方的整体。

    三. 去掉数字中的逗号

    具体示例

    在处理自然语言时123,000,000如果以标点符号分割,就会出现问题,好好的一个数字就被逗号肢解了,因此可以先下手把数字处理干净(逗号去掉)。

    分析

    数字中经常是3个数字一组,之后跟一个逗号,因此规律为:***,***,***

    正则式

    [a-z]+,[a-z]?

    参考代码3-1

    代码如下:


    import re

    sen = "abc,123,456,789,mnp"
    p = re.compile("\d+,\d+?")

    for com in p.finditer(sen):
    mm = com.group()
    print "hi:", mm
    print "sen_before:", sen
    sen = sen.replace(mm, mm.replace(",", ""))
    print "sen_back:", sen, '\n'

    结果

    技巧

    使用函数finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):

    搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。

    参考代码3-2

    代码如下:


    sen = "abc,123,456,789,mnp"
    while 1:
    mm = re.search("\d,\d", sen)
    if mm:
    mm = mm.group()
    sen = sen.replace(mm, mm.replace(",", ""))
    print sen
    else:
    break

    结果

    延伸

    这样的程序针对具体问题,即数字3位一组,如果数字混杂与字母间,干掉数字间的逗号,即把“abc,123,4,789,mnp”转化为“abc,1234789,mnp”

    思路

    更具体的是找正则式“数字,数字”找到后用去掉逗号的替换

    参考代码3-3

    代码如下:


    sen = "abc,123,4,789,mnp"
    while 1:
    mm = re.search("\d,\d", sen)
    if mm:
    mm = mm.group()
    sen = sen.replace(mm, mm.replace(",", ""))
    print sen
    else:
    break
    print sen

    结果

    四. 中文处理之年份转换(例如:一九四九年--->1949年)

    中文处理涉及到编码问题。例如下边的程序识别年份(****年)时

    代码如下:


    # -*- coding: cp936 -*-
    import re
    m0 = "在一九四九年新中国成立"
    m1 = "比一九九零年低百分之五点二"
    m2 = '人一九九六年击败俄军,取得实质独立'

    def fuc(m):
    a = re.findall("[零|一|二|三|四|五|六|七|八|九]+年", m)
    if a:
    for key in a:
    print key
    else:
    print "NULL"

    fuc(m0)
    fuc(m1)
    fuc(m2)

    运行结果

    可以看出第二个、第三个都出现了错误。

    改进——准化成unicode识别

    代码如下:


    # -*- coding: cp936 -*-
    import re
    m0 = "在一九四九年新中国成立"
    m1 = "比一九九零年低百分之五点二"
    m2 = '人一九九六年击败俄军,取得实质独立'

    def fuc(m):
    m = m.decode('cp936')
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", m)

    if a:
    for key in a:
    print key
    else:
    print "NULL"

    fuc(m0)
    fuc(m1)
    fuc(m2)

    结果

    识别出来可以通过替换方式,把汉字替换成数字。

    参考

    代码如下:


    numHash = {}
    numHash['零'.decode('utf-8')] = '0'
    numHash['一'.decode('utf-8')] = '1'
    numHash['二'.decode('utf-8')] = '2'
    numHash['三'.decode('utf-8')] = '3'
    numHash['四'.decode('utf-8')] = '4'
    numHash['五'.decode('utf-8')] = '5'
    numHash['六'.decode('utf-8')] = '6'
    numHash['七'.decode('utf-8')] = '7'
    numHash['八'.decode('utf-8')] = '8'
    numHash['九'.decode('utf-8')] = '9'

    def change2num(words):
    print "words:",words
    newword = ''
    for key in words:
    print key
    if key in numHash:
    newword += numHash[key]
    else:
    newword += key
    return newword

    def Chi2Num(line):
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", line)
    if a:
    print "------"
    print line
    for words in a:
    newwords = change2num(words)
    print words
    print newwords
    line = line.replace(words, newwords)
    return line

    推荐阅读
    • 如何实现织梦DedeCms全站伪静态
      本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
    • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
    • Java实战之电影在线观看系统的实现
      本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
    • 2018年人工智能大数据的爆发,学Java还是Python?
      本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
    • 本文介绍了求解gcdexgcd斐蜀定理的迭代法和递归法,并解释了exgcd的概念和应用。exgcd是指对于不完全为0的非负整数a和b,gcd(a,b)表示a和b的最大公约数,必然存在整数对x和y,使得gcd(a,b)=ax+by。此外,本文还给出了相应的代码示例。 ... [详细]
    • VScode格式化文档换行或不换行的设置方法
      本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
    • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
    • Nginx使用(server参数配置)
      本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
    • 基于layUI的图片上传前预览功能的2种实现方式
      本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
    • 电销机器人作为一种人工智能技术载体,可以帮助企业提升电销效率并节省人工成本。然而,电销机器人市场缺乏统一的市场准入标准,产品品质良莠不齐。创业者在代理或购买电销机器人时应注意谨防用录音冒充真人语音通话以及宣传技术与实际效果不符的情况。选择电销机器人时需要考察公司资质和产品品质,尤其要关注语音识别率。 ... [详细]
    • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
    • 如何去除Win7快捷方式的箭头
      本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
    • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
    • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
    • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
    author-avatar
    安小辰
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有