Python常用正则表达式语法和写法

今天因为看一个爬虫的例子,看到数据抓取的时候别人用的正则表达式去匹配想要的数据.当即对这个表达式感兴趣起来,仔细阅读了一下相关文档,对其有了大概的认识,索性写了一篇文章来介绍python中相关正则表达式的用法,以便自己日后参阅!

相关介绍

正则表达式是一种高度精度化的语言,我们可以用一段特定字符串生成的正则来过滤,替换,查找我们需要的数据.正则表达式在运行的的时候会被编译成一系列的码,并由C编写的匹配引擎执行,一般来说效率比一般的算法效率更高,但是却更不易于理解.大家也可以参考官方文档.

相关的库

Python的正则相关库用的最多的是RE模块了,因为是python的内置模块,我们只需要直接导入re模块即可使用其功能.

re模块常用函数用法

下面要介绍的相关函数非常重要,我们需要详细讲解一下!

1.compile 函数
    re.compile(pattern, flags=0)

compile函数类似一个正则工厂,他返回的是一个正则表达式的模式对象,我们可以用这个对象去加工任何需要加工的字符串.第一个参数传入的是正则的表达式字符串,第二个参数传递的是匹配的模式.

2.match 函数
pattern=re.compile('正则字符串')
pattern.match('要匹配的字符串')

match函数是一个匹配函数,我们用compile函数生成的工厂对象,对要加工的字符串进行匹配,如果有响应的字符串,就会返回,否者返回None.需要注意的是,match函数匹配字符串是从字符串开头匹配的,假如开头没有找到,就不会继续找下去!而且他只会返回最先匹配到的字符串,也就是说,假如可能一个字符串中有两个可以匹配的地方,他只会返回最先匹配到的那部分!
举个例子:

pattm=re.compile('a')   #a为正则字符串
pstr=pattm.match('aabcad')  #abcd是要匹配的字符串
    if pstr!=None:
        print(pstr.group())
    else:
        print('无匹配!')
>>>  a    #运行结果为a ,注意这个a是第一个a!

由于’adcd’字符串中第一位有我们需要匹配的正则字符a,所以成功匹配到了a!

pattm=re.compile('b')   #a为正则字符串
pstr=pattm.match('abcd')  #abcd是要匹配的字符串
    if pstr!=None:
        print(pstr.group())  #这里group函数下面会说
    else:
        print('无匹配!')
>>>  无匹配!    #运行没有匹配到

上面我们改了一下正则规则为b,就是说匹配的字符串第一个字符必须为b,否者匹配不成功!

3.search 函数
pattern=re.compile('正则字符串')
pattern.search('要匹配的字符串')

search 函数和match函数有个相同点就是,他只会返回最先匹配到那部分字符串!但是他和match不用的是,他不会只局限于在字符串的开头查找,他会查找整个字符串,直到找到匹配的部分为止!

pattm=re.compile('a')
pstr=pattm.search('baabcad')
    if pstr!=None:
        print(pstr.group())
    else:
        print('无匹配!')
>>>> a   #结果为a,这里的a是字符串出现的第一个a

假如字符串中没有匹配的字符,返回None

pattm=re.compile('f')
pstr=pattm.search('baabcad')
    if pstr!=None:
        print(pstr.group())
    else:
        print('无匹配!')
>>> 无匹配!    #字符串中没有匹配到f字符!
3.findAll 函数

findAll函数不但会查找整个字符串,并且会将匹配到的所有字符返回!而不仅限于返回第一个匹配到的!他会将返回的所有字符装载到一个列表对象返回.

pattm=re.compile('a')
pstr=pattm.findall('baabcad')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

 >>>>  ['a', 'a', 'a']   #返回了所有匹配到的a

同样,假如没有匹配到,会返回一个空列表对象

4.split函数

分割函数,类似于字符串分割.会根据正则字符为基准分割我们需要的字符串.

pattm=re.compile(':')
pstr=pattm.split('baa:bcad')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
>>> ['baa', 'bcad']   #根据:分割成了两个字符串

同样,假如没有匹配到,会返回一个空列表对象

正则中常用的特殊序列

符号 描述
\d 匹配任何十进制数字
\D 匹配任何非数字字符
\s 匹配任何空白字符(也就是空格)
\S 匹配任何非空格字符
\w 匹配任何字母数字字符
\W 匹配任何非字母数字字符

以上是6个常用的特殊序列,基本涵盖了我们所有字符串的过滤需求,序列间可以混用.
举个简单例子:

pattm=re.compile('\d')   #找出所有的十进制数字
pstr=pattm.findall('abcd1234')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>>>  ['1', '2', '3', '4']   #返回一个数组

混用例子:

  pattm=re.compile('\D\d')  #找出第一位是字母,第二位是数字的组合
  pstr=pattm.findall('abcd1234')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

  >>>  ['d1']    #成功匹配到d1

正则中常用的元字符

元字符在正则表达式中是最常用也是最不容易理解的字符,下面我们会来一一介绍几种最常用的元字符!

常用的元字符有以下几种:

.元字符:
. ^ $ * + ? { } [ ] \ | ( )

我们来一一举例子讲解:

pattm=re.compile('.',re.S)   #re.s代表匹配的模式,我们这里选择了所有的匹配模式,所有换行符也会被匹配
pstr=pattm.findall('abcd1234\n')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>> ['a', 'b', 'c', 'd', '1', '2', '3', '4', '\n']

. 代表一个任意的字符,这个字符默认包含所有的不包括换行符在内的所有字符,但通过改变匹配的模式,我们也可以做到匹配换行符,所有结果中返回了所有的匹配的结果!

^ 元字符符:
 pattm=re.compile('^abc',re.S)  #匹配abc为开头的字符
 pstr=pattm.findall('abcd1234\n')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>>  ['abc']   

^ 号表示匹配开头,上面例子我们相当于匹配字符串abc,切记这里不是匹配到整个abc开头的字符串哦!

$ 元字符
  pattm=re.compile('abc$',re.S)
  pstr=pattm.findall('abcd1234abc')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

  >>> ['abc']

$ 表示匹配结尾,上面例子就是相当于匹配abc,注意不是得到整个以abc结尾的字符串!

* 元字符
pattm=re.compile('a*',re.S)  #找出所有0个a乃至n个a的匹配
pstr=pattm.findall('bcaacaaab')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

 >>> ['', '', 'aa', '', 'aaa', '', '']

*代表倍数,只对该符号前一个字符有效,可以是0倍也可以是任意倍数,所以上面结果中,返回了空字符,因为0倍就是空字符!!

+ 元字符
pattm=re.compile('a+',re.S)
pstr=pattm.findall('bcaacaaab')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
>>>  ['aa', 'aaa']

元字符+和元字符*有点类似,只对该符号前一个字符有效,也是指重复,但是+不能匹配0倍,这是根本区别!

? 元字符
 pattm=re.compile('ca?t',re.S)  
 pstr=pattm.findall('catdddct')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

   >>> ['cat', 'ct']   

元字符?号也是重复类字符,但他表示可选,上面例子中a字符表示可选字符,他可匹配也可以不匹配,所以返回了两种匹配结果!

{ } 元字符

元字符{} 也是重复字符中的一员,只对该符号前一个字符有效,他比+和*更加的灵活

pattm=re.compile('a{1,2}',re.S)   #最少匹配1个a,最多匹配两个a
pstr=pattm.findall('fcabcdaaaef^')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
  >>> ['a', 'aa', 'a'] 

{}字符中可以有两个变量{m,n}, m表示最少的匹配倍数,n表示最大的匹配倍数.也可以只写一个变量{n},表示最大匹配n倍字符!

[] 元字符
pattm=re.compile('[abc]',re.S)
pstr=pattm.findall('abcdef')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>> ['a', 'b', 'c']

元字符[] 表示一个范围,相当于指定匹配一个范围类的字符,上图中想到与能匹配a,b,c三个字符范围,也可以写成[a-b]两者的效果相同,很多手机号的正则就是利用了该元字符,比如[0-9]取0到9范围内的一个数字!

还需要特别注意一点的是,在[]类中其他元字符将不会再有原有功能!

举个例子:

pattm=re.compile('[abc^]',re.S)  #按道理,^表示匹配开头,应该匹配abc开头的字符
pstr=pattm.findall('fcabcdef^')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')

  >>> ['c', 'a', 'b', 'c', '^']  #但结果却可以看出,因为[]类的原因,^元字符的作用消失了,被当成了普通的一个字符,返回了所有[]内字符范围的匹配
\ 元字符

\字符是一个比较有意思的字符,他主要有两种功能

一种是转义:

pattm=re.compile('\{',re.S)   #将{转义成普通字符匹配
pstr=pattm.findall('fc{aa{ef[')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
  >>> ['{', '{']

我们可以通过\将其他的元字符当成普通字符来匹配!

第二种是组合序列,通过一些特定的组合,组合成了一些特定功能的序列,比如我们上面提到的特殊序列\s,\w等

| 元字符
pattm=re.compile('a|b',re.S)
pstr=pattm.findall('abcdbcda')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>> ['a', 'b', 'b', 'a']

| 字符和java中的或有点类似,表示匹配前面部分或者后面部分,需要注意的是整个前面和后面部分!假如上面例子是abc|a表达式,表示匹配abc或者b,而不是先匹配ab,然后在c|a中选择一个,这种理解是错误的!

( ) 元字符

()字符代表分组,代表一个整体

pattm=re.compile('(abc)',re.S)  #代表匹配abc字符
pstr=pattm.findall('abcccababab')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
  >>> ['abc']

当然()的用法远远不止上面这么简单,我们可以在()中加入任何的一个匹配规则组成一个组,就可以实现无数种功能

比如:

pattm=re.compile('(^abc.+)',re.S)
pstr=pattm.findall('abcccababab')
    if pstr!=None:
        print(pstr)
    else:
        print('无匹配!')
 >>> ['abcccababab']

上面’(^abc.+)’ 正则,如果你认真看了上面所有的元字符,应该不难理解,表示匹配abc开头的任意长度的字符串,所以上面返回了整个字符串.

还有一点需要注意,记得最上面我们使用match和search函数的时候,往往打印都会使用group函数,入下:

pattm=re.compile('(^abc.+)',re.S)
pstr=pattm.search('abcccababab')
    if pstr!=None:
        print(pstr.group())  #使用过了group函数
    else:
        print('无匹配!')

其实这里的group函数对应的就是一个正则中的()组,group(1)代表第一个出现的()组的匹配,groupe(1,3)代表出现的第1个和第三个()组的匹配!

Q&A

以上我们就介绍完了,其实正则是一个很庞大的知识,远远不止我们文章介绍的那几种,但是基础我们一定要知道,这样在以后遇到一个复杂正则表达式的时候,至少能够看懂一个大概的样子.而不是一无所知!

你可能感兴趣的:(Python)