python核心编程第3版第1章 正则表达式【读书笔记】
来源:互联网 发布:符文战争桌游淘宝 编辑:程序博客网 时间:2024/05/17 13:39
什么是正则表达式
正则表达式为高级的本文模式匹配、抽取、与/或文本形式的搜索和替换功能提供了基础。简单地说,正则表达式(简称为regex)是一些由字符和特殊符号组成的字符串。
re模块
python通过标准库中的re模块来支持正则表达式
搜索和匹配的比较
“搜索”即在字符串任意部分中搜索匹配的模式,通过search()函数或方法来实现,搜索试图从字符串的任何位置开始匹配;
“匹配”是指判断一个字符串能否从起始处全部或者部分的匹配某个模式,通过调用match()函数或方法实现,匹配试图在字符串的开始位置进行匹配。
[A-Za-z]\w+的含义
[A-Za-z]\w+
的含义是第一个字符是字母,也就是说要么A-Z,要么a-z,后面是至少一个(+)由字母数字组成的字符(\w)。
没有使用任何特殊字符去匹配其他符号的模式
该模式没有使用任何特殊字符去匹配其他符号,而只匹配所描述的内容。能够匹配这个模式的只有包含“foo”的字符串。同理,对于字符串“python”和“abc123”也一样。
特殊符号和字符(元字符)
常见正则表达式符号和特殊字符
使用择一匹配符号匹配多个正则表达式模式 |
表示择一匹配的管道符号(|),表示一个“从多个模式中选择其一”的操作,它用于分隔不同的正则表达式。
如正则表达式模式为 at|home
,匹配的字符串为 at、home
。
匹配任意单个字符 .
点号或者句点(.)符号匹配除了换行符\n以外的任何字符。
从字符串起始或者结尾或者单词边界匹配 ^ $ \b \B
创建字符集(适用单字符) []
限定范围和否定 - ^
使用闭包操作符实现存在性和频数匹配 *, +, ?, {}
星号或称星号操作符(*)匹配其左边那个正则表达式出现零次或零次以上的情况(在计算机语言和编译器原理里,此操作符被叫做 Kleene 闭包操作符)。 * >=0
加号(+)操作符匹配一次或多次出现的正则表达式(也被称为正闭包操作符)。+>=1
问号操作符( ? )匹配零次或者一次出现的正则表达式。 ?=[0,1]
花括号操作符({ }),花括号里可以是单个的值,也可以是由逗号分开的一对值。如果是 一个值,如,{N},则表示匹配 N 次出现;如果是一对值,即,{M, N},就表示匹配 M 次到 N 次出现。
表示字符集的特殊字符
“\d”表示“0–9”。
“\w” 可用来表示整个字符数字的字符集,即相当于“[A-Za-z0-9_]”的缩写形式
“\s” 代表空白字符。
这些特殊字符的大写形式表示不匹配,比如,“\D” 表示非十进制数字的字符(等价于 “[^0-9]”)。
使用圆括号指定分组 ()
扩展表示法 (?…)
正则表达式和python语言
常见的正则表达式属性
使用 compile()编译正则表达式
对于一些特别的正则表达式编译,可选的标记可能以参数的形式给出,这些标记允许不区分大小写的匹配,他们可以通过按位或操作符(|)合并。
这些标记也可以作为参数适用于大多数re模块函数。如果想要在方法中使用这些标记,它们必须集成到已编译的正则表达式对象之中,或者需要使用直接嵌入到正则表达式本身(?F)
的标记,其中F是一个或者多个i(用于re.I/re.IGNORECASE)、m(用于re.M/re.MULTILINE)、s(用于re.DOTALL)等。如果想要同时使用多个,就把它们放在一起而不是使用按位或操作,例如,(?im)可以用于同时表示re.I/re.IGNORECASE和re.M/re.MULTILINE。
匹配对象以及group()和groups()方法
匹配对象是成功调用match()或者search()返回的对象。
匹配对象有两个主要的方法:group()和groups()。
group()要么返回整个匹配对象,要么根据要求返回特定子组,
groups()则仅返回一个包含唯一或者全部子组的元组。
使用match()方法匹配字符串
match()方法试图从字符串的起始部分对模式进行匹配。如果匹配成功,就返回匹配对象;如果失败,就返回None,匹配对象的group()方法用于显示那么成功的匹配。
>>> import re>>> m=re.match('foo','foo').group()>>> if m is not None:... m...'foo'
在实际操作中,最好不要省区if语句块,以避免AttributeError异常(None是返回的错误值,该值并没有group()方法)。
>>> m=re.match('foo','bar').group()Traceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: 'NoneType' object has no attribute 'group'
只要模式从字符串的起始部分开始匹配,即使字符串比模式长,匹配也仍然能够成功。
>>> m=re.match('foo','food on').group()>>> m'foo'
使用search()在一个字符串中查找模式(搜索与匹配的对比)
search()用于在任意位置对给定正则表达式模式搜索第一次出现的匹配情况,如果搜索到成功的匹配,就会返回一个匹配对象;否则,返回None。
搜索与匹配的对比
>>> m=re.match('foo','seafood')#匹配失败>>> if m is not None:... m.group()...>>> m
>>> m=re.search('foo','seafoof')#搜索成功,但匹配失败>>> if m is not None:... m.group()...'foo'
匹配多个字符串
>>> bt='bat|bet|bit' #正则表达式模式:bat bet bit>>> m=re.match(bt,'bat') #是匹配>>> if m is not None:... m.group()...'bat'>>> m=re.match(bt,'blt') #没有匹配>>> if m is not None: m.group()...>>> m=re.match(bt,'He bit me!') #不能匹配字符串>>> if m is not None: m.group()...>>> m=re.search(bt,'He bit me!') #搜索成功>>> if m is not None: m.group()...'bit'
匹配任意单个字符
>>> anyend='.end'>>> m=re.match(anyend,'bend') #点好匹配‘b’>>> if m is not None: m.group()...'bend'>>> m=re.match(anyend,'end') #不匹配任何字符>>> if m is not None: m.group()...>>> m=re.match(anyend,'\nend') #除了/n之外的任何字符>>> if m is not None: m.group()...>>> m=re.search('.end','The end.') #在搜索中匹配‘ ’>>> if m is not None: m.group()...' end'
>>> patt314='3.14'>>> pi_patt='3\.14'>>> m=re.match(pi_patt,'3.14') #精确匹配>>> if m is not None: m.group()...'3.14'>>> m=re.match(patt314,'3014') #点号匹配‘0’>>> if m is not None: m.group()...'3014'>>> m=re.match(patt314,'3.14') #点好匹配‘.’>>> if m is not None: m.group()...'3.14'
创建字符集 [ ]
>>> m=re.match('[cr][23][dp][o2]','c3po') #匹配>>> if m is not None: m.group()...'c3po'>>> m=re.match('[cr][23][dp][o2]','c2do') #匹配>>> if m is not None: m.group()...'c2do'>>> m=re.match('r2d2|c3po','c2do') #不匹配>>> if m is not None: m.group()...>>> m=re.match('r2d2|c3po','r2d2') #匹配>>> if m is not None: m.group()...'r2d2'
重复、特殊字符以及分组
>>> patt='\w+@(\w+\.)?\w+\.com'>>> re.match(patt,'nobody@xxx.com').group()'nobody@xxx.com'>>> re.match(patt,'nobody@www.xxx.com').group()'nobody@www.xxx.com'
>>> patt='\w+@(\w+\.)*\w+\.com'>>> re.match(patt,'nobody@www.xxx.yyy.zzz.com').group()'nobody@www.xxx.yyy.zzz.com'
>>> m=re.match('\w\w\w-\d\d\d','abc-123')>>> if m is not None: m.group()...'abc-123'>>> m=re.match('\w\w\w-\d\d\d','abc-xyz')>>> if m is not None: m.group()...
group() groups()用法
group()通常用于以普通方式显示所有匹配部分,也可用来获取各个匹配的子组。
groups()方法获得一个包含所有匹配子组的元组。
>>> m=re.match('(\w\w\w)-(\d\d\d)','abc-123')>>> m.group() #完整匹配'abc-123'>>> m.group(1) #子组1'abc'>>> m.group(2) #子组2'123'>>> m.groups() #全部子组('abc', '123')
>>> m=re.match('ab','ab') #没有子组>>> m.group()'ab'>>> m.groups()()>>> m=re.match('(ab)','ab') #一个子组>>> m.group()'ab'>>> m.group(1)'ab'>>> m.groups()('ab',)>>> m=re.match('(a)(b)','ab') #两个子组>>> m.group()'ab'>>> m.group(1)'a'>>> m.group(2)'b'>>> m.groups()('a', 'b')>>> m=re.match('(a(b))','ab') #两个子组>>> m.group()'ab'>>> m.group(1)'ab'>>> m.group(2)'b'>>> m.groups()('ab', 'b')
匹配字符串的起始和纪委以及单词边界
>>> m=re.search('^The','The end.') #匹配>>> if m is not None: m.group()...'The'>>> m=re.search('^The','end The.') #不作为起始>>> if m is not None: m.group()...>>> m=re.search(r'\bthe','bite the dog') #在边界>>> if m is not None: m.group()...'the'>>> m=re.search(r'\bthe','bitethe dog') #有边界>>> if m is not None: m.group()...>>> m=re.search(r'\Bthe','bitethe dog') #没有边界>>> if m is not None: m.group()...'the'
使用findall()和finditer()查找每一次出现的位置
findall()查询字符串中某个正则表达式模式全部的非重复出现情况,总是返回一个列表。如果findall()没有找到匹配的部分,就返回一个空列表,但如果匹配成功,列表将包含所有成功的匹配部分(从左到右按出现顺序排列)。
>>> re.findall('car','car')['car']>>> re.findall('car','scary')['car']>>> re.findall('car','carry the barcardi to the car')['car', 'car', 'car']
finditer()在匹配对象中迭代。
在单个字符串中执行两个不同分组的匹配
>>> s='This and that.'>>> re.findall(r'(th\w+) and (th\w+)',s,re.I)[('This', 'that')]>>> re.finditer(r'(th\w+) and (th\w+)',s,re.I).next().groups()('This', 'that')>>> re.finditer(r'(th\w+) and (th\w+)',s,re.I).next().group(1)'This'>>> re.finditer(r'(th\w+) and (th\w+)',s,re.I).next().group(2)'that'>>> [g.groups() for g in re.finditer(r'(th\w+) and (th\w+)',s,re.I)][('This', 'that')]
在单个字符串中执行单个分组的多重匹配
使用finditer()函数完成的所有额外工作都旨在获取它的输出来匹配findall()的输出。
>>> re.findall(r'(th\w+)',s,re.I)['This', 'that']>>> it=re.finditer(r'(th\w+)',s,re.I)>>> g=it.next()>>> g.groups()('This',)>>> g.group(1)'This'>>> g=it.next()>>> g.groups()('that',)>>> g.group(1)'that'>>> [g.group(1) for g in re.finditer(r'(th\w+)',s,re.I)]['This', 'that']
使用sub()和subn()搜索与替换
sub()实现搜索与替换功能,返回一个用来替换的字符串。
subn()实现搜索与替换功能,返回一个用来替换的字符串以及一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
>>> re.sub('X','Mr.Smith','attn: X\n\nDear X,\n')'attn: Mr.Smith\n\nDear Mr.Smith,\n'>>> re.subn('X', 'Mr. Smith', 'attn: X\n\nDear X,\n')('attn: Mr. Smith\n\nDear Mr. Smith,\n', 2)>>> print re.sub('X', 'Mr. Smith', 'attn: X\n\nDear X,\n')attn: Mr. SmithDear Mr. Smith,>>> re.sub('[ae]','X','abcdef')'XbcdXf'>>> re.subn('[ae]','X','abcdef')('XbcdXf', 2)
将美式的日期表示法格式转换为其他国家常用的格式
将美式的日期表示法MM/DD/YY{,YY}格式转换为其他国家常用的格式DD/MM/YY{,YY}。
\N,N是在替换字符串中使用的分组编号。
>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3','2/20/91')'20/2/91'>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3','2/20/1991')'20/2/1991'
在限定模式上使用split()分割字符串
如果给定分隔符不是使用特殊符号来匹配多重模式的正则表达式,那么re.split()与str.split()的工作方式相同。
>>> re.split(':','str1:str2:str3')['str1', 'str2', 'str3']
如果空格紧跟在五个数字或者两个大写字母(美国联邦州缩写)之后,就用split语句分割该空格。
>>> import re>>> DATA=(... 'Mountain View,VA94040',... 'Sunnyvale, VA',... 'Los Altos, 94023',... 'Cupertino 95014',... 'Palo Alto CA',... )>>> for datum in DATA:... print re.split(', |(?= (?:\d{5}|[A-Z]{2})) ',datum)...['Mountain View', 'VA', '94040']['Sunnyvale', 'VA']['Los Altos', '94023']['Cupertino', '95014']['Palo Alto', 'CA']
扩展符号
re.M/re.MULTILINE实现多行混合
>>> re.findall(r'(?i)yes','yes? Yes. YES!!')['yes', 'Yes', 'YES']>>> re.findall(r'(?i)th\w+','The quickest way is through this tunnel.')['The', 'through', 'this']>>> re.findall(r'(?im)(^th[\w ]+)',"""... This line is the first,... another line,... that line, it's the best... """)['This line is the first', 'that line']
re.S/re.DOTALL使点号能够用来表示\n符号
>>> re.findall(r'th.+','''... The first line... the second line... the third line... ''')['the second line', 'the third line']>>> re.findall(r'(?s)th.+','''... The first line... the second line... the third line... ''')['the second line\nthe third line\n']
re.X/VERBOSE
该标记允许用户通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜线转义中)来创建更易读的正则表达式。
>>> re.search(r'''(?x)... \((\d{3})\) #区号... [ ] #空白符... (\d{3}) #前缀... - #横线... (\d{4}) #终点数字... ''','(800) 555-1212').groups()('800', '555', '1212')
(?:…)对正则表达式进行分组
(?:…)可以对部分正则表达式进行分组,但是并不会保存该分组。
>>> re.findall(r'http://(?:\w+\.)*(\w+\.com)','http://google.com http://www.google.com http://code.google.com')['google.com', 'google.com', 'google.com']>>> re.search(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})','(800) 555-1212').groupdict(){'areacode': '800', 'prefix': '555'}
(?P< name >)
(?P< name >) 通过使用一个名称标识符而不是使用从1开始增加到N的增量数字来保存匹配,可以使用一个类似风格的\g< name >来检索它们。
>>> re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})','(\g<areacode>) \g<prefix>-xxxx','(800) 555-1212')'(800) 555-xxxx'
(?P=name)
可以在一个相同的正则表达式中重用模式,而不必稍后再次在(相同)正则表达式中指定相同的模式。
>>> bool(re.match(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?P<number>\d{4}) (?P=areacode)-(?P=prefix)-(?P=number) 1(?P=areacode)(?P=prefix)(?P=number)','(800) 555-1212 800-555-1212 18005551212'))True>>> bool(re.match(r'''(?x)... \((?P<areacode>\d{3})\)[ ](?P<prefix>\d{3})-(?P<number>\d{4})... [ ]... (?P=areacode)-(?P=prefix)-(?P=number)... [ ]... 1(?P=areacode)(?P=prefix)(?P=number)... ''', '(800) 555-1212 800-555-1212 18005551212'))True
正向前视断言(?…) 负向前视断言 (?!…)
>>> re.findall(r'\w+(?= van Rossum)',... '''... Gui van Rossum... Tim Peters... Alex Martrlli... Just van Rossum... Raymond Hettinger... ''')['Gui', 'Just']>>> re.findall(r'(?m)^\s+(?!noreply|postmaster)(\w+)', ... '''... sales@phptr.com... postmaster@phptr.com... eng@phptr.com... noreply@phptr.com... admin@phptr.com... ''')['sales', 'eng', 'admin']>>> ['%s@aw.com' %e.group(1) for e in re.finditer(r'(?m)^\s+(?!noreply|postmaster)(\w+)',... '''... sales@phptr.com... postmaster@phptr.com... eng@phptr.com... noreply@phptr.com... admin@phptr.com... ''')]['sales@aw.com', 'eng@aw.com', 'admin@aw.com']
使用条件正则表达式匹配
两字母的字符串必须由一个字母跟着另一个字母,不能同时拥有两个相同的字母。
>>> bool(re.search(r'(?:(x)|y)(?(1)y|x)','xy'))True>>> bool(re.search(r'(?:(x)|y)(?(1)y|x)','xx'))False
使用python原始字符串
退格符\b和正则表达式\b之间的差异
>>> m=re.match('\bblow','blow')>>> if m: m.group()...>>> m=re.match('\\bblow','blow')>>> if m: m.group()...'blow'>>> m=re.match(r'\bblow','blow')>>> if m: m.group()...'blow'
一些正则表达式示例
示例1-1 分割windows的tasklist命令 file对象
部分cmd命令——tasklist展示:映像名称 PID 会话名 会话# 内存使用========================= ======== ================ =========== ============System Idle Process 0 Services 0 4 KSystem 4 Services 0 9,212 Ksmss.exe 464 Services 0 544 Kcsrss.exe 708 Services 0 2,792 Kwininit.exe 816 Services 0 2,808 Kservices.exe 888 Services 0 5,220 Klsass.exe 904 Services 0 10,984 K
import osimport ref = os.popen('tasklist', 'r')for eachLine in f: print re.split(r'\s\s+|\t', eachLine.rstrip()) #使用str.rstrip()去除尾部的\nf.close()
部分python结果展示:['\xd3\xb3\xcf\xf1\xc3\xfb\xb3\xc6', 'PID \xbb\xe1\xbb\xb0\xc3\xfb', '\xbb\xe1\xbb\xb0#', '\xc4\xda\xb4\xe6\xca\xb9\xd3\xc3']['========================= ======== ================ =========== ============']['System Idle Process', '0 Services', '0', '4 K']['System', '4 Services', '0', '9,212 K']['smss.exe', '464 Services', '0', '544 K']['csrss.exe', '708 Services', '0', '2,796 K']['wininit.exe', '816 Services', '0', '2,808 K']['services.exe', '888 Services', '0', '5,220 K']['lsass.exe', '904 Services', '0', '10,968 K']
示例1-2 分割windows的tasklist命令 with语句
当使用with语句时,file对象的上下文管理器会自动调用f.close()
。
import osimport rewith os.popen('tasklist', 'r') as f: for eachLine in f: print re.split(r'\s\s+|\t', eachLine.rstrip())#使用str.rstrip()去除尾部的\n
部分python结果展示:['\xd3\xb3\xcf\xf1\xc3\xfb\xb3\xc6', 'PID \xbb\xe1\xbb\xb0\xc3\xfb', '\xbb\xe1\xbb\xb0#', '\xc4\xda\xb4\xe6\xca\xb9\xd3\xc3']['========================= ======== ================ =========== ============']['System Idle Process', '0 Services', '0', '4 K']['System', '4 Services', '0', '9,212 K']['smss.exe', '464 Services', '0', '544 K']['csrss.exe', '708 Services', '0', '2,796 K']['wininit.exe', '816 Services', '0', '2,808 K']['services.exe', '888 Services', '0', '5,220 K']['lsass.exe', '904 Services', '0', '10,968 K']
示例1-3 分割windows的tasklist命令 printf语句(2、3通用)
distutils.log.warn()
是一个单字符串输出函数,因此如果输出要复杂一些们就需要合并所有输出到一个字符串中,然后调用。
import osfrom distutils.log import warn as printfimport rewith os.popen('tasklist', 'r') as f: for eachLine in f: printf(re.split(r'\s\s+|\t', eachLine.rstrip()))
部分python结果展示:['\xd3\xb3\xcf\xf1\xc3\xfb\xb3\xc6', 'PID \xbb\xe1\xbb\xb0\xc3\xfb', '\xbb\xe1\xbb\xb0#', '\xc4\xda\xb4\xe6\xca\xb9\xd3\xc3']['========================= ======== ================ =========== ============']['System Idle Process', '0 Services', '0', '4 K']['System', '4 Services', '0', '9,212 K']['smss.exe', '464 Services', '0', '544 K']['csrss.exe', '708 Services', '0', '2,796 K']['wininit.exe', '816 Services', '0', '2,808 K']['services.exe', '888 Services', '0', '5,220 K']['lsass.exe', '904 Services', '0', '10,968 K']
示例1-4 处理DOS环境下tasklist命令的输出
import osimport ref = os.popen('tasklist /nh', 'r')for eachLine in f: print re.findall(r'([\w.]+(?: [\w.]+)*)\s\s+(\d+) \w+\s\s+\d+\s\s+([\d,]+ K)', eachLine.rstrip())f.close()
部分cmd命令——tasklist /nh展示:System Idle Process 0 Services 0 4 KSystem 4 Services 0 9,228 Ksmss.exe 464 Services 0 544 Kcsrss.exe 708 Services 0 2,800 Kwininit.exe 816 Services 0 2,804 Kservices.exe 888 Services 0 5,144 K部分python结果展示:(已截断)[][('System Idle Process', '0', '4 K')][('System', '4', '9,228 K')][('smss.exe', '464', '544 K')][('csrss.exe', '708', '2,800 K')][('wininit.exe', '816', '2,804 K')][('services.exe', '888', '5,088 K')]
更长的正则表达式示例
示例1-5 用于正则表达式练习的数据生成器
该脚本为正则表达式练习创建随机数据,然后将生成的数据输出到屏幕。
from random import randrange, choicefrom string import ascii_lowercase as lc # string.ascii_lowercase是字母表中拥有26个小写字母的序列集合from sys import maxintfrom time import ctimetlds = ('com', 'edu', 'net', 'org', 'gov') # 高级域名集合for i in xrange(randrange(5, 11)): dtint = randrange(maxint) # 随机生成一个整数 dtstr = ctime(dtint) # 使用time.ctime()函数将该整数转换为日期 llen = randrange(4, 8) # login is shorter login = ''.join(choice(lc) for j in range(llen)) # random.choice()函数的功能是接受一个序列,然后返回该序列的一个随机元素 dlen = randrange(llen, 13) # domain is longer dom = ''.join(choice(lc) for j in xrange(dlen)) print '%s::%s@%s.%s::%d-%d-%d' % (dtstr, login, dom, choice(tlds), dtint, llen, dlen)
输出结果:Wed Mar 20 13:40:35 2002::geom@mnfdlm.edu::1016602835-4-6Sun Feb 21 00:44:33 1993::owlvlhs@bjigjefgj.net::730226673-7-9Mon Feb 11 04:03:20 2008::sdsggc@fzmbgrgposr.gov::1202673800-6-11Fri May 05 14:00:38 1978::rlom@gneqeyswh.edu::263196038-4-9Thu Dec 26 16:38:22 2024::swkd@pvxgk.gov::1735202302-4-5Sun Oct 28 08:02:14 1990::vdqwqn@kgwkux.com::657072134-6-6Thu Dec 30 01:30:21 2010::likjtte@agrmmvmrlnm.gov::1293643821-7-11Sun Apr 27 01:53:57 2014::faua@owdsabmwpo.gov::1398534837-4-10Tue Oct 02 16:26:34 1979::dpsv@csqoe.edu::307700794-4-5
匹配字符串
>>> import re>>> data='Wed Mar 20 13:40:35 2002::geom@mnfdlm.edu::1016602835-4-6'>>> patt='^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)'>>> m=re.match(patt,data)>>> m.group()'Wed'>>> m.group(1)'Wed'>>> m.groups()('Wed',)
分组 ^()
>>> patt='^(\w{3})'>>> m=re.match(patt,data)>>> if m is not None: m.group()...'Wed'>>> m.group(1)'Wed'
>>> patt='^(\w){3}'>>> m=re.match(patt,data)>>> if m is not None: m.group()...'Wed'>>> m.group(1) # 子组1持续被下一个字符替换'd'
搜索、匹配与贪婪
>>> patt='\d+-\d+-\d+'>>> re.search(patt,data).group()'1016602835-4-6'
>>> patt='.+(\d+-\d+-\d+)' # +是一个贪婪的操作符>>> re.match(patt,data).group()'Wed Mar 20 13:40:35 2002::geom@mnfdlm.edu::1016602835-4-6'>>> re.match(patt,data).group(1) # 贪婪匹配'5-4-6>>> patt='.+?(\d+-\d+-\d+)' # ?是一个非贪婪操作符>>> re.match(patt,data).group(1)'1016602835-4-6
- python核心编程第3版第1章 正则表达式【读书笔记】
- Python核心编程---读书笔记:第15章 正则表达式
- Python核心编程---读书笔记:第1章~第3章
- 《python核心编程(第三版)》第1章 正则表达式 练习答案
- Python核心编程第15章正则表达式练习答案
- 《Python核心编程》第15章 正则表达式 练习
- python核心编程第3版第3章 因特网客户端编程【读书笔记】
- python核心编程第3版第2章 网络编程【读书笔记】
- python核心编程读书笔记--第3章 基础语句语法
- python核心编程读书笔记--第1章eclipse插件
- Python核心编程---读书笔记:第7章~第13章
- 《Python核心编程》读书笔记—正则表达式
- Python核心编程---读书笔记:第4章 Python对象
- Python核心编程---读书笔记:第13章 面向对象编程
- python核心编程---读书笔记:第16章 网络编程
- python核心编程---读书笔记:第18章 多线程编程
- python核心编程---读书笔记:第21章 数据库编程
- Python核心编程---读书笔记:第5章 数字
- android.os.networkonmainthreadexception怎么解决
- 带头结点链表大例题
- POJ 3581 启发:后缀数组求最小表示
- 冠军挑战赛之我的冠军经历
- Flask学习总结笔记(11) -- 利用itsdangerous实现用户身份确认
- python核心编程第3版第1章 正则表达式【读书笔记】
- 自动瘦脸与眼睛放大美颜算法
- 集合的最优分组问题
- Python实现k-means算法
- Linux下使用Wireshark进行抓包分析(含SIP和RTP包)
- Unity T4M 中文讲解
- PPPOE和pppd的流程详解--good
- configure: error: C compiler cannot create executables
- Proguard总结