设为首页 收藏本站
查看: 1101|回复: 0

[经验分享] Python的正则表达式

[复制链接]

尚未签到

发表于 2015-11-30 14:42:47 | 显示全部楼层 |阅读模式
  阅读目录


  • 简单介绍
  • 正则表达式元字符
  • re模块
  • 实例
  • 参考资料

  今天学习了Python的正则表达式,开始觉得一点都看不懂!后面通过理解+实践 终于学会了正则表达式的基本用法


简单介绍


  • 正则表达式(regular expression)是一种用形式化语法描述的文本匹配模式,在需要处理大量文本处理的应用中有广泛的使用,IDE中的搜索常用正则表达式作为搜索模式
  • 如果学过linux\unix系统的都知道如sed、egrep、grep、awk这类的命令,它们是非常强大的文本处理工具,几乎所有的语言都有对正则表达式的支持,有的直接在语法中支持,有的使用扩展库的形式
  • 它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,就认为它"匹配"了,否则,该字符串就是不合法的
  • Python的正则表达式就是使用的扩展库re,Python提供re模块,包含所有正则表达式的功能
  • 正则表达式也是用字符串表示的,所以首先了解如何用字符来描述字符!正则表达式中,如果直接给出字符,就是精确匹配

正则表达式元字符


  • 字符

  . 可以匹配任意字符                  'py.'可以匹配'pyc,pyo,py! ...'
\ 转义字符,使后一个字符改变原来的意思          'a\c.'可以匹配'a.c'

                             'a\\c'可以匹配'a\c'
  []字符集(字符类),可以逐个列出,也可以指定范围
   [0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线
   [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'
   [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串
   [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)



  • 预定义字符集(可以写在字符集[…]中)

  \d : 一个数字[0-9]                 '0\d0'可以匹配'010,020,030 ...'
\D : 一个非数字[^\d]                'a\Dc'可以匹配'abc,azc ...'
\w : 字母或者数字[A-Za-z0-9]             'a\wc'可以匹配'abc,adc,a1c...'
\W : 非字母,非数字[^\w]              'a\Wc'可以匹配'a c'
\s : 空白符(制表符,空格,换行符等)         'a\sc'可以匹配'a c'
\S : 非空白符[^\s]                  'a\Sc'可以匹配'a c'



  •   边界匹配(不消耗待匹配字符串中的字符)


  ^ 字符或行的开始                    '^abc'可以匹配'abc'
$ 字符或行的结束                   'abc$'可以匹配'abc'
\A 字符串的开始                   '\Aabc'可以匹配'abc'
\Z 字符串结束                    'abc\Z'可以匹配'abc'
\b 一个单词开头或者末尾的空串            'a\b!bc'可以匹配'a!bc'
\B 不在一个单词开头或末尾的空串[^\b]         'a\Bc'可以匹配'abc'




import re
the_str = "This is some text -- with punctuation"  
re.search(r'^\w+', the_str).group(0)         # This
re.search(r'\A\w+', the_str).group(0)        # This  
re.search(r'\w+\S*$', the_str).group(0)      # punctuation  
re.search(r'\w+\S*\Z', the_str).group(0)     # punctuation  
re.search(r'\w*t\W*', the_str).group(0)      # text --  
re.search(r'\bt\w+', the_str).group(0)       # text  
re.search(r'\Bt*\B', the_str).group(0)       # 没有匹配  

  • 数量词(用在字符或(…)之后)

  * 匹配前一个字符0次或无限次              'ab*'可以匹配'ab,abc,abccc ...'
+ 匹配前一个字符1次或无限次              'ab+'可以匹配'abc,abccc'
?匹配前一个字符0次或1次                'ab?'可以匹配'ab,abc'
  {m,n} 之前元素最少出现m次,最多n次          'ab{1,2}c'可以匹配'abc,abbc'
{m} 之前的元素最少出现m次               'ab{2}c'可以匹配'abbc'





import re  
re.search("^vforb?ox$", "vforox")              #True  
re.search("^vforb?ox$", "vforbox")              #True   
re.search("^ab\*", "abbbbbbb")                    #True,返回"abbbbbbb"
re.search("^ab\*?", "abbbbbbb")                   #True,返回"a"  
re.search("^ab+", "abbbbbbb")                     #True,返回"abbbbbbb"
re.search("^ab+?", "abbbbbbb")                    #True,返回"ab"  

  • 逻辑与分组

  | 左右表示任意一个                     'abc|def'可以匹配'abc,def'
() 表达式将作为分租 '(abc){2}'可以匹配'abcabc'
    分组作为一个整体,可以后接数量词表达式仅 | 在该组有效  'a(123|456)c'可以匹配'a456c'


re模块


  • 有了以上的准备知识,我们就可以在Python中使用正则表达式了
  • 需要注意一个问题:Python的字符串本身也用\转义



>>> a = 'vforbox\\-010'                #python的字符串
>>> print a     #打印输出对象 a
vforbox\-010


  • 上面的结果对应的正则表达式字符串不变,为了防止漏写或者更直观!这里强力推荐使用python的r前缀,这样的话就不用考虑转义问题了,并且写出来的表达式也更直观了




>>> a = r'vforbox\-010'                #python的字符串
>>> print a     #打印输出对象 a
vforbox\-010


  • re.search(pattern,string,flag=0)

  搜索文本中的匹配的模式是最常用的,以模式和文本作为输入,如果有匹配则返回一个Match对象,否则返回None
每个Match对象包括相关的匹配信息:原字符串、正则表达式和匹配的文本在字符串中的位置




import re  
pattern = "this"  
text = "Does this text match the pattern?"  
match = re.search(pattern, text)    # 返回一个Match对象  
print match.re.pattern  # 要匹配的正则表达式"this"
print match.string      # 匹配的文本"Does this match the pattern?"  
print match.start()        # 匹配的开始位置 5
print match.end()       # 匹配的结束位置 9


  • re.compile(pattern,flag=0)

  如果程序中频繁的使用到同一个正则表达式,每次使用的时候都写一遍正则表达式不仅不高效而且会大大增加出错的几率,re提供了compile函数将一个表达式字符串编译为一个RegexObject
模块级函数会维护已编译表达式的一个缓存,而这个缓存是的大小是有限制的!直接使用已经编译的表达式可以避免缓存查找的开销,并且在加载模块时就会预编译所有的表达式




import re  
regex = re.compile("this")  
text = "Does this text match the pattern?"  
match = regex.search(text)  
if match:  
print "match"  
match.group(0)        #返回匹配的字符串   
else:
print "not match"  


  • re.findall(pattern, string, flag=0)

  使用search会返回匹配的单个实例,使用findall会返回所有匹配的不重叠的子串




import re  
pattern = 'ab'  
text = 'abbaaabbbbaaaaaa'  
re.findall(pattern, text)   # 返回['ab', 'ab']  

  • re.finditer(pattern, string, flag=0)

  finditer会返回一个迭代器,会生成Match实例,不像findall()返回字符串




import re  
pattern = 'ab'  
text = 'abbaaabbbbaaaaaa'  
match = re.finditer(pattern, text)   
for m in match:
print m.start()  
print m.end()

  以上的例子会分别输出两次匹配结果的起始位置和结束位置

  

  正则匹配默认采用的是贪婪算法,也就是说会re在匹配的时候会利用尽可能多的输入,而使用?可以关闭这种贪心行为,只匹配最少的输入
  例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"

  

  用组来解析匹配,简单的说就是在一个正则表达式中有几个小括号()将匹配的表达式分成不同的组,使用group()函数来获取某个组的匹配,其中0为整个正则表达式所匹配的内容,后面从1开始从左往右依次获取每个组的匹配,即每个小括号中的匹配
  使用groups()可以获取所有的匹配内容




import re  
the_str = "--aabb123bbaa"  
pattern = r'(\W+)([a-z]+)(\d+)(\D+)'  
match = re.search(pattern, the_str)   
match.groups()          # ('--', 'aabb', '123', 'bbaa')
match.group(0)          # '--aabb123bbaa'  
match.group(1)          # '--'  
match.group(2)          # 'aabb'  
match.group(3)          # '123'  
match.group(4)          # 'bbaa'

  python对分组的语法做了扩展,可以对每个分组进行命名,这样便可以使用名称来调用
  语法:(?P<name>pattern),使用groupdict()可以返回一个包含了组名的字典




import re  
the_str = "--aabb123bbaa"  
pattern = r'(?P<not_al_and_num>\W+)(?P<al>[a-z]+)(?P<num>\d+)(?P<not_num>\D+)'  
match = re.search(pattern, the_str)   
match.groups()                   # ('--', 'aabb', '123', 'bbaa')  
match.groupdict()                # {'not_al_and_num': '--', 'not_num': 'bbaa', 'num': '123', 'al': 'aabb'}  
match.group(0)                          # '--aabb123bbaa'  
match.group(1)                          # '--'  
match.group(2)                          # 'aabb'  
match.group(3)                          # '123'  
match.group(4)                          # 'bbaa'   
match.group('not_al_and_num')           # '--'
match.group('al')                       # 'aabb'  
match.group('num')                      # '123' '
match.group('not_num')                  # 'bbaa'

  以上的group()方法在使用的时候需要注意,只有在有匹配的时候才会正常运行,否则会抛错,所以在不能保证有匹配而又要输出匹配结果的时候,必须做校验

  

  在re中可以设置不通的标志,也就是search()和compile()等中都包含的缺省变量flag。使用标志可以进行完成一些特殊的要求,如忽略大小写,多行搜索等




import re  
the_str = "this Text"  
re.findall(r'\bt\w+', the_str)   # ['this']  
re.findall(r'\bt\w+', the_str, re.IGNORECASE) # ['this', 'Text']  

实例  


  • 用正则表达式来判断邮箱地址(通过交互)



#!/usr/bin/python
#coding=utf-8
#File Name: mail.py
#Author: vforbox
#Mail: vforbox@gmail.com
#Created Time: 2015-9-14
import re
t1=raw_input("Input e-mail address:")
if re.match(r'^[a-zA-Z0-9]+.*[a-zA-Z0-9]@+[a-zA-Z0-9]+.(com|cn|org)$',t1):
print 'This is the correct e-mail address'
else:
print 'This is the wrong e-mail address'



[iyunv@test test]# python mail.py
Input e-mail address:vforbox@gmail.com
This is the correct e-mail address
[iyunv@test test]# python mail.py
Input e-mail address:vforbox@gmail.tk
This is the wrong e-mail address


  • 用正则表达式来判断国内区号电话号码(通过交互)



#!/usr/bin/python
#_*_coding:utf-8 _*_
#File Name: number.py
#Author: vforbox
#Mail: vforbox@gmail.com
#Created Time: 2015-9-14
import re
t1 =raw_input("输入 区号-号码:")
if re.match(r'^\d{3}-+\d{3,8}$', t1):
print '这是正确的电话号码'
else:
print '这是错误的电话号码'



[iyunv@test test]# python number.py
输入 区号-号码:023-12345678
这是正确的电话号码
[iyunv@test test]# python number.py
输入 区号-号码:023 12345678
这是错误的电话号码


参考资料


  • 廖雪峰 python2.7-正则表达式
  • segmentfault团队-正则表达式1  正则表达式2
  • 菜鸟教程-python-正则表达式
  • AstralWind
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145470-1-1.html 上篇帖子: 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。 下篇帖子: 【转载】Deep Learning Python Tutorial
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表