Python中的正则表达式
正则表达式简介
处理文本和数据是件大事。如果你不信,请仔细看看先如今的计算机主要都在做些什么工作:文字处理,网页填表,来自数据库的信息流,股票报价信息,新闻列表,这个清单会不断增长。因为我们可能不知道这些需要计算机编程处理文本或数据的具体内容,所以能把这些文本或数据以某种可被计算机识别和处理的模式表达出来是非常有用的。
正则表达式使用的特殊符号和字符
常见符号和字符
符号 | 说明 | 正则表达式样例 |
---|---|---|
literal | 匹配字符串的值 | foo |
re1\re2 | 匹配正则re1或re2 | foo|bar |
.(点) | 匹配任何字符(换换行符.空白除外) | b.b |
^ | 匹配字符串的开始(开头) | ^Dear |
$ | 匹配字符串的结尾(结尾) | /bin/*sh/$ |
* | 匹配前面出现的正则表达式零次或多次 | [A-z0-9]* |
+ | 匹配前面的正则表达式一次或多次 | [a-z]+\.com |
? | 匹配前面出现的正则表达式零次或一次 | goo? |
{N} | 匹配前面出现的正则表达式N次 | [0-9]{3} |
{M,N} | 匹配前面出现的正则表达式最少M次,最多N次 | [0-9]{3,5} |
[ ] | 匹配字符组里出现的任意一个字符 | [Atlan] |
[x-y] | 匹配字符从X到Y中的任意一个字符 | [0-9] |
[^ ] | 不匹配此字符组中出现的任意一个字符 | [^0-9A-zatlan] |
() | 匹配括号中的正则表达式用于分组 | (0-9a-z) |
关闭表格
特殊字符
符号 | 说明 | 正则表达式样式 |
---|---|---|
\d | 匹配任何数字,和[0-9]一样(\D是\d的反义) | data\d |
\w | 匹配任何数字字符字符,和[A-Za-z0-9]一样(\W是\s的反义) | \w+ |
\s | 匹配任何空白字符和【\n\t\r\v\f】相同(\S是\s反义) | of\she |
\b | 匹配单词结尾(\B是\b的反义) | \bthe |
\nn | 匹配以保存的分组 | price\1 |
\c | 逐一匹配特殊字符c(取消它的特殊含义,按字面匹配) | \.,\* |
\A(\Z) | 匹配字符串的起始和结束 | \ADear |
关闭表格
正则表式和Python语言
re模块:核心函数和方法
函数/方法 | 描述 |
模块的函数 | |
compile(pattern,flags=0) | 对正则表达式模式pattern进行编译,flags是可选表示符,并返回一个regex对象 |
re模块的函数和regex对方的方法 | |
match(pattern,string,flags=0) | 尝试用正则表达式模式pattern匹配字符串string,flags是可选表示符,如果匹配成功,则返回一个匹配对象,否则返回None |
scarch(pattern,string,flags=0) | 在字符串string中搜索正则表达式模式pattern的第一次出现,flags是可选表示符,如果匹配成功,返回一个匹配对象;否则返回一个None |
findall(pattern,string,flags=0) | 在字符串string中搜索正则表达式模式pattern的所有(非重复)的出现;返回一个对象列表 |
finditer(pattern,string,flags=0) | 和findall()相同,但返回的不是列表而是迭代器;对于每个匹配,改迭代器返回一个匹配对象 |
split(pattern,string,max=0) | 根据正则表达式pattern中的分隔符把字符string分隔成为一个列表,返回成功匹配的列表,最多分隔max次(默认是分隔所有匹配字符) |
sub(pattern,repl,string,max=0) | 把字符串string中所有匹配正则表达式pattern的地方替换成repl,如果max的值没有给出,则对所有匹配的地方进行替换(subn(),会返回一个表示替换次数的数值) |
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字符串可以是多行的,忽略空白字符,并可以添加注释 |
匹配对象和group(),groups()方法
在处理正则表达式时,除regex对象外,还有另一个对象类型-匹配对象。这些对象是在match()或search()被成功调用之后所返回的结果。匹配对象有两个group()和groups().
group()方法或者返回所有匹配对象或是根据要求返回某个特定子组
groups()则很简单,返回一个包含唯一或所有子组的元祖。如果正则表达式中没有子组的话,groups()将返回一个空元祖,而group()依然会返回全部对象
重复·特殊字符和子组
正则表达式中最常见的情况包括特殊字符的使用,正则表达式的重复出现,以及使用圆括号对匹配模式的各部分进行分组或提取操作。我们曾看到一个关于简单电子邮件地址的正则表达式(“\w+@\w+.com”).或许我们想要匹配的邮件地址比这个正则表达式的允许的要多。比如,为了在域名前添加主机名支持,即支持‘www.Atlan.com’,而不是只允许’Atlan.com’做整个域名,那就必须修改现有的正则表达式。为了主机名是可选的,我们要写一个模式匹配主机名(后面跟一个句点),然后用问号?表示此模式可出现0次或1次,表示此部分是可选的,再把这个可选正则表达式插入到我们前面的那个正则表达式中去:“\w+@(\w+.)?\w.com从下面的梨子中可以看出,这个表达式允许’.com’前有一个或两个名字:
>>> patt = '\w+@(\w+\.)?\w\.com'
>>> re.match(patt,'Altan@atlan.com').group()
'Atlan@atlan.com'
>>> re.match(patt,'Atlan@www.atlan.com').group()
'Atlan@www.atlan.com'
接下来我们可以用一下模式进一步扩展我们的梨子,允许任意数量的子域名存在。(注意细节)
>>> patt = '\w+@(\w+\.)*\w\.com'
>>> re.match(patt,'Altan@a.t.l.a.n.com').group()
'Altan@a.t.l.a.n.com'
但是仅用字母或数字组成的字符不能满足邮件地址中可能出现的各种字符。上述正则表达式不匹配如’atlan-www.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()
....
>>>
上面代码中,一个正则表达式被用来匹配有三个字母或数组组成的字符串,在接着三个数字的字符串,这个正则表达式匹配 “abc-123”,但不匹配 ‘abc-xyz’.现在修改正则表达式,使他能分别提取包含字母或数字的部分和仅数字的部分。
>>> m = re.match('(\w\w\w)-(\d\d\d\)','abc-123')
>>> m.group()
'abc-123'
>>> m.group(1)
'abc'
>>> m.group(2)
'123'
>>> m.groups()
('abc','123')
下面让我们通过一个简单的梨子,了解一下什么是子组
>>> m = re.match('ab','ab') #无子组
>>> m.group() #完全匹配
'ab'
>>> m.groups() #所有匹配的子组
()
>>>
>>> m = re.match('(ab)','ab') #一个子组
>>> m.group() #所有匹配’ab‘
'ab'
>>> m.group(1) #匹配子组1
'ab'
>>> m.groups() #所有匹配子组
('ab')
>>>
>>> m = re.match('(a)(b)','ab') #两个子组
>>> m.group() #完全匹配
'ab'
>>> m.group(1) #匹配的子组1
'a'
>>> m.group(2) #匹配的子组2
'b'
>>> m.groups() #所有匹配的子组的元祖
('a','b')
>>>
>>> m =re.match('(a(b))','ab') #两个子组
>>> m.group() #所有匹配部分
'ab'
>>> m.group(1) #匹配到的子组1
'ab'
>>> m.group(2) #匹配到的子组2
'b'
>>> m.groups() #所有匹配的子组元祖
('ab','b')