标签:python
VII Python(6)基础知识(re正则表达式)
正则表达式RE(regular 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}(m和n是十进制整数,前一个字符至少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匹配python、py2、py3而不匹配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‘) #(注意此处表示0或1或2后面跟两个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
标签:python
原文地址:http://jowin.blog.51cto.com/10090021/1791578