码迷,mamicode.com
首页 > 编程语言 > 详细

VII Python(6)基础知识(re正则表达式)

时间:2016-06-22 11:06:58      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:python

VII Python6)基础知识(re正则表达式)

正则表达式REregular expression)是一种小型的、高度专业化的编程语言,肉嵌在python中,通过re模块实现;

当发现有问题用正则表达式可解决时,于是将面临两个问题;

RE模式被编译成一系统的字节码,再由匹配引擎(C写的)执行,RE语言相对小型和受限(功能有限,并非所有字符串处理都能用RE完成);

re模块提供了顶级函数调用,常用的有:findall()sub()match()search()subn()split()

 

In [1]: import re

In [2]: re.<TAB>

re.DEBUG        re.L            re.S            re.U            re.compile      re.findall      re.search       re.sub

re.DOTALL       re.LOCALE       re.Scanner      re.UNICODE      re.copy_reg     re.finditer     re.split        re.subn

re.I            re.M            re.T            re.VERBOSE      re.error        re.match        re.sre_compile  re.sys

re.IGNORECASE   re.MULTILINE    re.TEMPLATE     re.X            re.escape       re.purge        re.sre_parse    re.template

In [2]: help(re.search)   #search()方法用于在字符串中搜索模式第一次匹配的位置,若有匹配到返回的是对象的内存地址,若没匹配到则返回空)

search(pattern, string, flags=0)

In [3]: help(re.findall)   #findall()将匹配到的字符串打包为列表)

findall(pattern, string,flags=0)

   Return a list of all non-overlapping matches in the string.

In [4]: help(re.compile)

compile(pattern, flags=0)

   Compile a regular expression pattern, returning a pattern object.

In [5]: help(re.finditer)

finditer(pattern, string,flags=0)

   Return an iterator over all non-overlapping matches in the

   string.  For each match, theiterator returns a match object.

In [6]: help(re.subn)

subn(pattern, repl,string, count=0, flags=0)

   Return a 2-tuple containing (new_string, number).

In [7]: help(re.match)

match(pattern, string,flags=0)

   Try to apply the pattern at the start of the string, returning

    amatch object, or None if no match was found.

 

正则中默认是打开大小写敏感的,可在标志位处使用re.IGNORECASE取消;

正则中不区分数字,全是字符;

正则默认是贪婪模式,在条件符合时尽可能多的匹配,可在.+后加上?进入非贪婪模式即最小匹配范围;

字符匹配(普通字符和元字符):

普通字符(大多数字符一般都会和自身匹配,例如r‘test‘会和字符串‘test‘完全匹配);

元字符;

 

元字符(11个):

. ^  $  * +  ?  {} []  \  |  ()

.点(匹配换行符以外的任意字符);

^(匹配行首,字符串的开始位置,除非设置标志位re.MULTILINE,在re.MULTILINE模式里也可匹配字符串中的每个换行);

$(匹配行尾,行尾被定义为要么是字符串尾,要么是一个换行字符后的任何位置);

*(指定前一个字符匹配0次或任意次,贪婪模式,匹配引擎会尝试重复尽可能多的次数,不超过整数界定范围20亿);

+(前一个字符匹配一次或任意次,默认贪婪模式,若要用非贪婪模式(最小匹配模式)+后跟?);

?(匹配前一个字符0次或1次,可理解为它用于标识某事物是可选的);

{m,n}mn是十进制整数,前一个字符至少m次重复,最多n次;忽略m则下边界是0,忽略n则上边界是无穷大(20亿));

[](常用来指定一个字符集,如[abc][a-z],元字符在字符集中不起作用;字符集中开始处使用^,补集匹配不在区间内的字符);

\num\后跟不同的字符表示不同的意义;若当作转义符用可取消元字符本身的意义;\d等同于[0-9]\D等同于[^0-9]\s等同于[\t\n\r\f\v]\S等同于[^\t\n\r\f\v]\w等同于[a-zA-Z0-9_]\W等同于[^a-zA-Z0-9_]

()(分组)

 

注:

*等同于{0,}+等同于{1,}?等同于{0,1};尽量使用*+?这三个符号,因为既美观而且更关键的是正则引擎内部会对这三个符号进行优化,进而执行效率要高,而不要用等同的{0,}{1,}{0,1}

*+区别(*匹配的前一个字符可以是0次,+要至少是一次);

[]中的元字符代表其本身,不具备元字符的功能;

 

\序号(若序号为单个数字,则是引用序号对应的子组所匹配的字符串,子组的序号从1开始计算;若序号以0开头或是3个字符长度时,那么不会被用于对应的子组,而是用于匹配八进制的数字所表示的ASCII表对应的字符);

\A(等同于^,脱字符);

\Z(等同于$

\b(匹配单词边界,单词被定义为Unicode的字母数字或下划线,注意下划线也是单词的一部分);

\B(与\b相反,匹配非单词边界,例如py\B匹配pythonpy2py3而不匹配py py.py!);

\d(对于Unicode(str类型)模式,匹配任何一个数字,包括[0-9]和其它数字字符,若开启了re.ASCII标志,只匹配[0-9];对于8位模式(bytes类型)匹配[0-9]中任何一个数字);

\D(与\d相反,匹配任何非Unicode的数字,若开启了re.ASCII标志,则相当于匹配[^0-9]);

\s(对于Unicode(str类型)模式,匹配Unicode中的空白字符,包括[\t\n\r\f\v]及其它空白字符,若开启了re.ASCII标志,只匹配[\t\n\r\f\v];对于8位模式(bytes类型),匹配ASCII中定义的空白字符,即[\t\n\r\f\v]);

\S(与\s相反,匹配任何非Unicode中的空白字符,若开启了re.ASCII标志,则相当于匹配[^\t\n\f\r\v]

\w(对于Unicode(str类型)模式,匹配任何以Unicode的单词字符,基本上所有语言字符都可匹配,也包括数字下划线[a-zA-Z0-9],若开启了re.ASCII标志则只匹配[a-zA-Z0-9];对于8位模式(bytes类型),匹配ASCII中定义的字母数字);

\W(与\w相反,匹配任何非Unicode的单词字符,若开启了re.ASCII标志,则相当于[^a-zA-Z0-9]);

 

转义符的特殊情况:

\a \b  \f  \n \r  \t  \u \U  \v  \x  \\

\b(通常用于单词边界,只有在字符类中才表示backspace);

\u\U(只在Unicode模式下才会被识别);

\num(八进制转义是有限制的,如果第1个数字是0,或如果有3个八进制数字,那么就被认为是八进制;其它情况则被认为是子组引用;至于字符串,八进制转义最多只能是3个数字的长度);

 

flags标志位:

ASCII(简写A,使得转义符\w\b\d\s只能匹配ASCII字符);

DOTALL(简写S,使得.点匹配任何符号,包括换行符,无敌状态);

IGNORECASE(简写I,匹配时不区分大小写);

LOCALE(简写L,支持当前的语言设置);

MULTILINE(简写M,多行匹配(要查找的内容为多行),影响^$);

VERBOSE(简写X,启用详细的正则表达式,正则的书写为多行时);

 

编译正则表达式:

re模块提供了一个正则表达式引擎的接口,可将REstring编译成对象并用它们进行匹配;

如果要重复的使用某个正则表达式,可将正则表达式编译成模式对象,使用re.compile()来编译;

若只需查找或匹配一次使用模块级别的方法,如re.findall(r‘[A-Z]‘,‘string‘);若要多次使用正则表达式,在循环情况下,就要先编译再进行调用,这样使用更方便;

In [6]: help(re.compile)

compile(pattern, flags=0)

   Compile a regular expression pattern, returning a pattern object.

In [2]: p=re.compile(r‘[A-Z]‘)

In [3]: type(p)

Out[3]: _sre.SRE_Pattern

In [4]: p.search(‘I love FishC.com‘)

Out[4]: <_sre.SRE_Match at 0x2bd91d0>

In [5]: p.findall(‘I love FishC.com‘)

Out[5]: [‘I‘, ‘F‘, ‘C‘]

In [8]: p.<TAB>

p.findall     p.flags       p.groups      p.pattern     p.search      p.sub        

p.finditer    p.groupindex  p.match      p.scanner     p.split       p.subn 

In [8]: help(p.findall)   #(找到RE匹配的所有子串,将它们作为列表返回)

findall(string[, pos[,endpos]]) --> list.

In [10]: print p   #(编译后的正则表达式为对象,可在该对象上应用以上方法,()中直接跟要查找的字符串)

<_sre.SRE_Pattern object at0x268cc10>

In [23]: help(p.finditer)   #(找到RE匹配的所有子串,将它们作为迭代器返回)

finditer(string[, pos[,endpos]]) --> iterator.

In [24]: help(p.match)   #(决定RE是否在刚开始的位置匹配)

match(string[, pos[,endpos]]) --> match object or None.

In [25]: help(p.search)   #(扫描字符串,找到这个RE匹配的位置)

search(string[, pos[,endpos]]) --> match object or None.

注:

p.match()p.search()若没匹配到,它们将返回None,否则返回MatchObject的实例(内存地址),MatchObject所支持的方法:group()start()end()span();在实际程序中,最常见的做法是将MatchObject保存在一个变量里,检查是否为None

In [6]: m=p.match(‘I love FishC.com!‘)

In [7]: m.<TAB> 

m.end       m.expand     m.groupdict  m.lastgroup m.pos        m.regs       m.start     

m.endpos    m.group      m.groups     m.lastindex  m.re        m.span       m.string 

In [7]: help(m.group)   #(返回被RE匹配的字符串)

group([group1, ...]) -> str or tuple.

   Return subgroup(s) of the match by indices or names.

   For 0 returns the entire match.

In [8]: help(m.start)   #(返回匹配刚开始的位置)

start([group=0]) -> int.

   Return index of the start of the substring matched by group.

In [9]: help(m.end)   #(返回匹配结束的位置)

end([group=0]) -> int.

   Return index of the end of the substring matched by group.

In [10]: help(m.span)   #(返回一个元组包含匹配开始、结束的位置)

span([group]) -> tuple.

   For MatchObject m, return the 2-tuple (m.start(group), m.end(group)).

In [20]: p=re.compile(r‘[a-z]‘)

In [21]: m=p.search(‘I love FishC‘)

In [22]: m.group()

Out[22]: ‘l‘

 

举例(match()search()方法在程序中常用来判断是否匹配到):

[root@localhost ~]# vim re_match.py

------------------script start-------------

#!/usr/bin/python2.7

#filename:re_match.py

import re

p=re.compile(r‘[a-z]‘)

m=p.match(‘string123‘)

if m:

       print ‘Match found:‘,m.group()

else:

       print ‘No match‘

--------------script end----------------

[root@localhost ~]# python2.7 re_match.py

Match found: s

 

举例:

In [8]: str1=‘I love FishC.com!‘

In [10]: re.search(r‘FishC‘,str1)

Out[10]: <_sre.SRE_Match at0x24fa648>

In [11]: re.findall(r‘FishC‘,str1)  

Out[11]: [‘FishC‘]

In [12]: re.findall(r‘.‘,str1)   #(点号表示换行符以外的任意字符,此处全部匹配到)

Out[12]:

[‘I‘,

 ‘ ‘,

 ‘l‘,

 ‘o‘,

 ‘v‘,

 ‘e‘,

 ‘ ‘,

 ‘F‘,

 ‘i‘,

 ‘s‘,

 ‘h‘,

 ‘C‘,

 ‘.‘,

 ‘c‘,

 ‘o‘,

 ‘m‘,

 ‘!‘]

In [13]: re.findall(r‘Fish.‘,str1)

Out[13]: [‘FishC‘]

In [14]: re.findall(r‘Fish\.‘,str1)   #(加入转义符表示元字符本身,此处未匹配到内容)

Out[14]: []

In [15]: re.findall(r‘\d‘,‘I loveFishC.com!123‘)   #\d表示单个任意数字)

Out[15]: [‘1‘, ‘2‘, ‘3‘]

In [16]: re.findall(r‘\d\d\d‘,‘123 456FishC‘)

Out[16]: [‘123‘, ‘456‘]

In [18]: re.findall(r‘[aeiou]‘,‘string‘)   #[]创建字符类,仅匹配中括号中的一个字符)

Out[18]: [‘i‘]

In [19]: re.findall(r‘[A-Z]‘,‘String‘)   #(正则中默认是打开大小写敏感的,可用re.IGNORECASE取消)

Out[19]: [‘S‘]

In [20]: re.findall(r‘[a-z]‘,‘Hello‘)

Out[20]: [‘e‘, ‘l‘, ‘l‘, ‘o‘]

In [21]:re.findall(r‘[a-z]‘,‘HELLO‘,re.IGNORECASE)

Out[21]: [‘H‘, ‘E‘, ‘L‘, ‘L‘, ‘O‘]

In [22]: re.findall(r‘ab{3}c‘,‘abbbc‘)   #{NUM}表示重复的次数)

Out[22]: [‘abbbc‘]

In [23]: re.findall(r‘ab{3,10}c‘,‘abbbbc‘)

Out[23]: [‘abbbbc‘]

In [24]: re.findall(r‘[0-255]‘,‘188‘)   #(注意此处表示012后面跟两个5

Out[24]: [‘1‘]

In [25]: re.findall(r‘[0-255]‘,‘1155‘)

Out[25]: [‘1‘, ‘1‘, ‘5‘, ‘5‘]

In [28]:re.findall(r‘(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}(?![\.\d])‘,‘192.168.1.1‘)   #(匹配IP

Out[28]: [‘192.168.1.1‘]

In [29]:re.findall(r‘(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}(?![\.\d])‘,‘192.168.23.125‘)

Out[29]: [‘192.168.23.125‘]

In [30]:re.findall(r‘\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$‘,‘127.0.0.1‘)

Out[30]: [‘127.0.0.1‘]

In [31]: re.findall(r‘Fish(C|D)‘,‘www.FishC.com‘)   #(若使用分组(),默认仅显示匹配到的分组内的内容)

Out[31]: [‘C‘]

In [33]: re.findall(r‘^FishC‘,‘FishC.com‘)

Out[33]: [‘FishC‘]

In [34]: re.findall(r‘FishC$‘,‘I loveFishC‘)

Out[34]: [‘FishC‘]

In [35]:re.findall(r‘(FishC)\1‘,‘FishCFishC‘)  #\后跟序号1,引用序号对应的子组所匹配的字符串,子组的序号从1开始计算)

Out[35]: [‘FishC‘]

In [36]: re.findall(r‘\.‘,‘FishC.com‘)   #\.表示点本身)

Out[36]: [‘.‘]

In [37]: re.findall(r‘[.]‘,‘FishC.com‘)   #(中括号中的元字符代表其本身,不具备元字符的功能)

Out[37]: [‘.‘]

In [38]: re.findall(r‘[\n]‘,‘FishC.com\n‘)   #(匹配回车符)

Out[38]: [‘\n‘]

In [39]: re.findall(r‘[^a-z]‘,‘FishC.com‘)   #[]中的^是取反,若取反^只能放在中括号的最前面)

Out[39]: [‘F‘, ‘C‘, ‘.‘]

In [40]: re.findall(r‘FishC{3}‘,‘FishCCCC‘)   #{NUM}仅对前面的单个字符做重复)

Out[40]: [‘FishCCC‘]

In [41]: re.findall(r‘(FishC){2,5}‘,‘FishCFishCFishC‘)

Out[41]: [‘FishC‘]

In [42]:re.findall(r‘<.+>‘,‘<html><title>I loveFishC</title></html>‘)   #(正则默认是贪婪模式,在条件符合时尽可能多的匹配,可在.+后加上?进入非贪婪模式)

Out[42]: [‘<html><title>I loveFishC</title></html>‘]

In [43]:re.findall(r‘<.+?>‘,‘<html><title>I love FishC</title></html>‘)

Out[43]: [‘<html>‘, ‘<title>‘,‘</title>‘, ‘</html>‘]

In [46]: re.findall(r‘\bFishC\b‘,‘FishC.comFishC_com FishC‘)   #(匹配单词边界,下划线也是单词的一部分)

Out[46]: [‘FishC‘, ‘FishC‘]

In [48]: re.findall(r‘py\B‘,‘python py2py3‘)   #(匹配非单词边界)

Out[48]: [‘py‘, ‘py‘, ‘py‘]

In [49]: re.findall(r‘py\B‘,‘py py. py!‘)

Out[49]: []

In [18]:re.findall(r‘^010-?\d{8}‘,‘010-12345678‘)

Out[18]: [‘010-12345678‘]

In [19]: re.findall(r‘ab+‘,‘abbbbc‘)    #(贪婪模式)

Out[19]: [‘abbbb‘]

In [20]: re.findall(r‘ab+?‘,‘abbbbbc‘)    #(非贪婪模式,最小匹配)

Out[20]: [‘ab‘]

In [23]: re.findall(r‘csvt.net‘,‘csvt.net‘)

Out[23]: [‘csvt.net‘]

In [24]:re.findall(r‘csvt.net‘,‘csvt\nnet‘)

Out[24]: []

In [25]:re.findall(r‘csvt.net‘,‘csvt\nnet‘,re.S)  #(开启了re.DOTALL使得点号可顶替任何字符,包括换行符)

Out[25]: [‘csvt\nnet‘]

举例(标志位re.M):

In [2]: s=‘‘‘

  ...: hello csvt

  ...: csvt hello

  ...: hello csvt

  ...: csvt hello

  ...: ‘‘‘

In [3]: re.findall(r‘‘^csvt‘,s)   #(不开re.M标志位的情况下,是无法匹配多行的)

 File "<ipython-input-3-ca4a73fa0c50>", line 1

   re.findall(r‘‘^csvt‘,s)

                          ^

SyntaxError: EOL while scanning stringliteral

In [4]: re.findall(r‘^csvt‘,s,re.M)

Out[4]: [‘csvt‘, ‘csvt‘]

举例(标志位re.X):

In [5]: tel=r‘‘‘

  ...: \d{3,4}

  ...: -?

  ...: \d{8}

  ...: ‘‘‘

 

In [6]: re.findall(tel,‘010-12345678‘)

Out[6]: []

In [7]: re.findall(tel,‘010-12345678‘,re.X)

Out[7]: [‘010-12345678‘]

举例(分组):

In [8]:re.findall(r‘\w{3,}@\w+(\.com|\.cn)‘,‘zzz@csvt.com‘)   #(当有分组时findall会优先返回查找到的分组中的内容)

Out[8]: [‘.com‘]

In [9]: re.findall(r‘\w{3,}@\w+(\.com|\.cn)‘,‘zzz@csvt.cn‘)

Out[9]: [‘.cn‘]

In [10]:re.findall(r‘\w{3,}@\w+(\.com|\.cn)‘,‘zzz@csvt.org‘)

Out[10]: []

In [11]:re.match(r‘\w+@\w+(\.com|\.cn)‘,‘jowin@163.com‘)

Out[11]: <_sre.SRE_Match at0x22e8198>

In [12]: s=‘‘‘

   ....: aaa srt hello src=csvt

  ....: yes

  ....: hello src=python hello

  ....: ‘‘‘

In [13]: re.findall(r‘hello src=(.+)‘,s)   #(查找指定内容中包含hello src=……的内容)

Out[13]: [‘csvt‘, ‘python hello‘]

 


str字符串替换:

In [5]: help(str.replace)

S.replace(old, new[,count]) -> string

In [6]: s=‘hello csvt‘

In [7]: s.replace(‘csvt‘,‘python‘)

Out[7]: ‘hello python‘

In [9]: s.replace(r‘c..t‘,‘python‘)   #(字符串所支持的方法和操作是不支持re的)

Out[9]: ‘hello csvt‘

 

 

re.sub()re.subn()(正则中的替换):

In [10]: help(re.sub)

sub(pattern, repl,string, count=0, flags=0)

In [11]: help(re.subn)

subn(pattern, repl,string, count=0, flags=0)

In [13]: re.sub(r‘c..t‘,‘csvt‘,‘caat cvvt ccct‘)

Out[13]: ‘csvt csvt csvt‘

In [14]: re.subn(r‘c..t‘,‘csvt‘,‘caat cvvt ccct‘)   #subn不仅打印替换的内容,还打印替换了几次)

Out[14]: (‘csvt csvt csvt‘, 3)

 

 

str.split()

In [16]: help(str.split)

S.split([sep[,maxsplit]]) -> list of strings

In [17]: ip=‘192.168.23.128‘

In [18]: ip.split(‘.‘)

Out[18]: [‘192‘, ‘168‘, ‘23‘, ‘128‘]

 

re.split

In [15]: help(re.split)

split(pattern, string,maxsplit=0, flags=0)

In [20]: re.split(r‘[\+\-\*]‘,‘1+2-3*4‘)   #(中括号中的元字符将失去本身的意义,但此例中-表示范围,在不加转义符的前提下,要么-不能放在两个元字符中间,要么将-放到最后即可)

Out[20]: [‘1‘, ‘2‘, ‘3‘, ‘4‘]

In [21]: re.split(r‘[+*]‘,‘1+2*3‘)

Out[21]: [‘1‘, ‘2‘, ‘3‘]

In [22]: re.split(r‘[+*-]‘,‘1+2-3*4‘)

Out[22]: [‘1‘, ‘2‘, ‘3‘, ‘4‘]


本文出自 “Linux运维重难点学习笔记” 博客,请务必保留此出处http://jowin.blog.51cto.com/10090021/1791578

VII Python(6)基础知识(re正则表达式)

标签:python

原文地址:http://jowin.blog.51cto.com/10090021/1791578

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!