06.正则表达式基本知识
目录
六、正则表达式基本知识字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取 正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。 所以我们判断一个字符串是否是合法的Email的方法是:
6.1 字符匹配和字符长度匹配因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。
要匹配变长的字符,在正则表达式中,用 来看一个复杂的例子: 我们来从左到右解读一下:
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。 如果要匹配 但是,仍然无法匹配 6.2 进阶要做更精确地匹配,可以用
6.3 re模块有了准备知识,我们就可以在Python中使用正则表达式了。Python提供 s = ‘ABC-001‘ # Python的字符串 # 对应的正则表达式字符串变成: # ‘ABC-001‘ 因此我们强烈建议使用Python的 s = r‘ABC-001‘ # Python的字符串 # 对应的正则表达式字符串不变: # ‘ABC-001‘ 先看看如何判断正则表达式是否匹配: >>> import re >>> re.match(r‘^d{3}-d{3,8}$‘,‘010-12345‘) <_sre.SRE_Match object at 0x1026e18b8> >>> re.match(r‘^d{3}-d{3,‘010 12345‘) >>>
test = ‘用户输入的字符串‘ if re.match(r‘正则表达式‘,test): print ‘ok‘ else: print ‘failed‘ 6.4 切分字符串用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码: >>> ‘a b c‘.split(‘ ‘) [‘a‘,‘b‘,‘‘,‘c‘] 嗯,无法识别连续的空格,用正则表达式试试:(很实用) >>> re.split(r‘s+‘,‘a b c‘) [‘a‘,‘c‘] 无论多少个空格都可以正常分割。加入 >>> re.split(r‘[s,]+‘,‘a,b,c d‘) [‘a‘,‘c‘,‘d‘] 再加入 >>> re.split(r‘[s,;]+‘,b;; c d‘) [‘a‘,‘d‘] 6.5 分组分组也是相当重要,记住了
>>> m = re.match(r‘^(d{3})-(d{3,8})$‘,‘010-12345‘) >>> m <_sre.SRE_Match object at 0x1026fb3e8> >>> m.group(0) ‘010-12345‘ >>> m.group(1) ‘010‘ >>> m.group(2) ‘12345‘ 如果正则表达式中定义了组,就可以在 提取子串非常有用。来看一个更凶残的例子: >>> t = ‘19:05:30‘ >>> m = re.match(r‘^(0[0-9]|1[0-9]|2[0-3]|[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$‘,t) >>> m.groups() (‘19‘,‘05‘,‘30‘) 这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期: ‘^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$‘ 对于 6.6 贪婪分组最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的 >>> re.match(r‘^(d+)(0*)$‘,‘102300‘).groups() (‘102300‘,‘‘) 由于 >>> re.match(r‘^(d+?)(0*)$‘,‘102300‘).groups() (‘1023‘,‘00‘) 6.7 编译(让匹配更加高效)当我们在Python中使用正则表达式时,re模块内部会干两件事情:
如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配: >>> import re # 编译: >>> re_telephone = re.compile(r‘^(d{3})-(d{3,8})$‘) # 使用: >>> re_telephone.match(‘010-12345‘).groups() (‘010‘,‘12345‘) >>> re_telephone.match(‘010-8086‘).groups() (‘010‘,‘8086‘) 编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对象的方法时不用给出正则字符串。 6.8 小结正则表达式非常强大,要在短短的一节里讲完是不可能的。要讲清楚正则的所有内容,可以写一本厚厚的书了。如果你经常遇到正则表达式的问题,你可能需要一本正则表达式的参考书。 请尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email: [email?protected] [email?protected] 版本二可以验证并提取出带名字的Email地址: <Tom Paris> [email?protected] 版本一 #-*- coding:utf-8 -*- import re re_compile = re.compile(r‘^w+@w+.w+$‘) #re_compile = re.compile(r‘^(w+)@(w+)(.[a-z]{3})$‘) #出错,一个括号代表一个分组,错误不在@ #re_compile = re.compile(r‘^(w+)@(w+)(.)([a-z]{3})$‘) #出错,错误在第四个分组,[a-z]前不应该加转义符号re_compile2 = re.compile(r‘^(w+)@(w+).([a-z]{3})$‘) re_compile3 = re.compile(r‘^(w+)@([a-z]{2,10}).([a-z]{3})$‘) re_compile4 = re.compile(r‘^(w+)@([a-z]{2,10}).([a-z]{3})$‘) re_compile5 = re.compile(r‘^(w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$‘) #忽略大小写的匹配,注意要将a-z和A-Z放到一个中括号里面 re_compile6 = re.compile(r‘^(w*.*w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$‘) #这个能匹配[email?protected],但是不能匹配[email?protected] re_compile7 = re.compile(r‘^(w*.*w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$‘) #这个功能很强大,两个邮件都可以匹配 re_compile8 = re.compile(r‘^(w*.*w+)@([a-zA-Z]{2,10}).(com)$‘) #只能匹配尾缀为com的邮件 email = ‘[email?protected]‘ email1 = ‘[email?protected]‘ #考验如何将‘bill.gates‘放入到一个分组中 m = re_compile.match(email) m1 = re_compile8.match(email1) m.group(0) #用于检测是否匹配成功 m.group(0) 版本二: import re it = ‘<Tom Paris> [email?protected]‘ item = re.spilt(r‘[&;s]‘) re_compile = re.compile() 6.9 正则表达式字符(仅仅用于查询)构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。 正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。 6.9.1 普通字符普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
6.9.2 特殊字符所谓特殊字符,就是一些有特殊含义的字符,如上面说的 runoob 中的 ,简单的说就是表示任何字符串的意思。如果要查找字符串中的 * 符号,则需要对 * 进行转义,即在其前加一个 : runo*ob 匹配 runo*ob。 许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符?放在它们前面。
]
限定符
定位符 定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,b 描述单词的前或后边界,B 表示非单词边界。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |