re模块和正则表达式

re模块

          

            

            讲正题之前我们先来看一个列子
            这是京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示。
            假如我们随意的在手机号码这个栏输入一个11111111,它会提示我们格式有误。
            这个功能是怎么实现的呢?
            假如现在你用Python写一段代码,类似:
            phone_unmber = input("please input your phone number:")
            你怎么判断这个phone_number是合法的呢?
            根据手机号码一共11位并且是只以13、14、15、18开头的数字这些特点,我们用Python写了如下代码:

     判断手机号码是否合法1:

        

          while True:
              phone_unmber = input("please input your phone number:")
              if len(phone_unmber) == 11\
                and phone_unmber.isdigit()\
                and (phone_unmber.startswith('13')\
                or phone_unmber.startswith('14')\
                or phone_unmber.startswith('15')\
                or phone_unmber.startswith('18')):
                print('是合法的手机号码')
              else:
                print("不是合法的手机号码")

            


              这是你的写法,现在我要展示一下我的写法:

                判断手机号码是否合法2:

                  import re
                  phone_unmber = input("please input your phone number:")
                  if re.match('^(13|14|15|18)[0-9]{9}$',phone_unmber):
                    print("是合法的手机号码")
                  else:
                    print("不是合法的手机号码")

                

                对比上面的两种写法,此时此刻,我要问你你喜欢那种方法?你肯定还是会说第一种,为什么?因为第一种不用学呀。
                但是如果现在有一个文件,我让你从整个文件里匹配出所有的手机号码,你用Python给我写个试试?
                但是学了今天的技能之后,分分钟帮你搞定!!!

 

                今天我们要学习Python里的re模块和正则表达式,学会了这个就可以帮我们解决刚刚的疑问。正则表达式不仅存在Python领域,在整个变成届都占有举足轻重的地位

              正则表达式和re模块:

        

                  不管一个你是不是去做Python开发,只要你是一个程序员就应该了解正则表达式的基本使用。如果未来你要在爬虫领域发展,你就更应该好好学习这方面的知识。      

                    但是你要知道,re模块本质上和正则表达式没有一毛钱关系。re模块和正则表达式的关系,类似于time模块和时间的关系你没有学习Python之前,也不知道有一个time模块但是你已经认识时间了,12:30就代表中午十二点半(这个时间可好,一般这会儿就该下课了)。

                  时间有自己的格式,年月日时分秒,12个月,365天。。。。已经成为了一种规则。你也牢记于心了。time模块只不过是Python提供给我们的可以方便我们操作时间的一个工具而已

                  

                  正则表达式本身也是和Python没有 什么关系,就是匹配字符串内容的一种规则。
            官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定的组合,组成一个“规则字符串”,这个“规则字符串”用来表示对字符串的一种过滤逻辑。

 

 

          正则表达式

             

            一说规则我已经知道你很晕了。现在就让我们先来看一些实际的应用。在线测试工具            http://tool.chinaz.com/regex/

            首先你要知道的是,谈到正则,就只和字符串相关了。在我给你提供的工具中,你输入的每一个字都是一个字符串。

            其次,如果在一个位置的一个值,不会出现什么变化,那么是不需要规则的。

            比如你要用“1”去匹配“1”,或者“2”去匹配“2”,直接就可以匹配上,这连Python的字符串操作都可以轻松做到。
            那么在之后我们更多要考虑的是在同一个位置上可以出现的字符的范围。

 

          字符组:

              

            字符组:[字符组]

            

            在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示时间三种方式
字符分为很多类,比如数组,字母,标点等等。
            假如你现在要求一个位置“只能出现一个数字”那么这个位置上的字符只能是1、2、...9这10个数字之一。

          

          图片

 

      字符:

          图片

 

      量词

          图片

 

      .^$

          图片

      *+?{}

          图片

 

      注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

          图片

       

      字符集[][^]

          图片

 

      分组()与或|[^]  

          身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部为数字组成,首位不能为0;如果是18位,则前面17位全部是数字,末位可能是数字或者x,下面我们用正则来表示:

          图片

 

      转义符:\

          在正则表达式中,有很多有特殊意义的元字符,比如\d和\s等,如果要在正则匹配正常的“\d”而不是“数字”就需要对“\“进行转义,变成”\\“

          在Python中,无论 是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次“\d”,字符串中药写成“\\d”,那么正则里就要写成“\\\\d”,这样太麻烦了。这个时候我们就用到了r“\d”这个概念,此时的正则是r“\d”就可以了。

 

          图片

      贪婪匹配

          贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配。

          图片

          几个常用的费贪婪匹配Pattern

          

            *? 重复任意次,但尽可能少重复
            +? 重复1次或者更多次,但尽可能少重复
            ?? 重复0次或1次,但尽可能少重复
            {n,m}? 重复n次到m次,但尽可能少重复
            {n,} 重复n次以上,但尽可能少重复

      

      .*?的用法:

            

            .是任意字符串
            *是取0至无限长度
            ?是非贪婪匹配模式

            何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:

              .*?x

             就是取前面任意长度的字符,知道一个x出现。

      

      re模块下的常用方法

            

              import re
              ret = re.findall('a','eva egon yuan')#返回所有满足匹配条件的结果,放在列表里
              print(ret)
              输出:
              ['a', 'a']


              import re
              ret = re.search('a','eva egon yuan').group()
              print(ret)
              输出:
              a

              #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None

              

              import re
              ret = re.match('a','abc').group() #同search,不过尽在字符串开始处进行匹配
              print(ret)
              输出:
              a

              import re
              ret = re.split('[ab]','abcd')#先按“a”分割得到‘’和‘bcd’,在对‘’和‘bcd’分别按‘b’分割
              print(ret)
              输出:
              ['', '', 'cd']

              import re
              ret = re.sub('\d','H','eva3egon4yuan5',1)#将数字替换成"H",参数1表示只替换1个
              print(ret)
              输出:
              evaHegon4yuan5

              import re
              ret = re.subn('\d','H','eva3egon4yuan4')#将数字替换成“H”,返回的元祖(替换的结果,替换了多少次)
              print(ret)
              输出:
              ('evaHegonHyuanH', 3)

              obj = re.compile('\d{3}')#将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
              ret = obj.search('abc123eeee')#正则表达式对象调用search,参数为待匹配的字符串
              print(ret.group())
              输出:
              123

              import re
              ret = re.finditer('\d','as3st4324a')#finditer返回一个存放匹配结果的迭代器
              print(ret)#<callable_iterator object at 0x00000000025F8198>
              print(next(ret).group)#查看第一个结果
              print(next(ret).group)#查看第二个结果
              print([i.group() for i in ret])#查看剩余的左右结果
              输出:
              <callable_iterator object at 0x00000000025F8198>
              <built-in method group of _sre.SRE_Match object at 0x00000000024F59F0>
              <built-in method group of _sre.SRE_Match object at 0x00000000024F59F0>
              ['3', '2', '4']

          注意:

          findall的优先级查询     

            import re 

            ret = re.findall('www.(baidu|oldboy).com','www.oldboy.com')#这是因为findall会优先把匹配结果里的内容返回,如果想要匹配结果,取消权限即可

            

            print(ret)
            输出:
            ['oldboy']

            ret = re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
            print(ret)
            输出:
            ['www.oldboy.com']

        split的优先级查询

            

            ret = re.split("\d+","eva3egon4yuan")
            print(ret)
            输出:
            ['eva', 'egon', 'yuan']

            ret = re.split("(\d+)","eva3egon4yuan")
            rint(ret)
            输出:
            ['eva', '3', 'egon', '4', 'yuan']

            #在匹配部分加上()之后所切出的结果是不同的,
            #没有()的没有保留所匹配的项,但是有()的却能保留了匹配的项
            #这个在某些需要保留匹配部分的使用过程是风场重要的。

 

 

 

      综合练习扩展

          

          1匹配标签

            import re

            ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
            #还可以在分组中利用?<naem>的形式给分组起名字
            print(ret.group('tag_name')) 
            输出:h1
            print(ret.group())#
            输出:<h1>hello</h1>

            ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
            #如果不给组起名字,也可以用\序列号来找到对应的组,表示要找的内容和前面的组内容一致
            #获取的匹配结果可以直接用group(序列)拿到对应的值
            print(ret.group(1))
            输出:
            h1
            print(ret.group())
            输出:
            <h1>hello</h1>

 

      

      2匹配整数:

 

          

              import re
              ret =re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")
              print(ret)
              输出:
              ['1', '2', '60', '40', '35', '5', '4', '3']

              ret = re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
              print(ret)
              输出:
              ['1', '-2', '60', '', '5', '-4', '3']

              ret.remove("")
              print(ret)
              输出:
              ['1', '-2', '60', '5', '-4', '3']

 

 

      flags有很多可选值:

          

            re.I(IGNORECASE)忽略大小写,括号内是完整的写法
            re.M(MULTILINE)多行模式,改变^和$的行为
            re.S(DOTALL)点可以匹配任意字符,包括换行符
            re.L(LOCALE)做本地化识别的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境,不推荐使用
            re.U(UNICODE) 使用\w \W \s \S \d \D使用取决于unicode定义的字符属性。在python3中默认使用该flag
            re.X(VERBOSE)冗长模式,该模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注释

posted @ 2018-05-15 11:32  zhangliang666  阅读(118)  评论(0编辑  收藏  举报