Python基础学习之正则表达式
1. python 中的正则匹配步骤
用import re 导入正则表达式模块;
用re.compile() 创建一个regex对象,最好使用原始字符串;即在字符串前加r;
向regex对象的search() 中传入想查找的字符串。返回值为一个Match对象;
调用Match对象的group() 方法,返回实际匹配文本字符串;
例子:寻找电话号码
import re phoneNumRegex = re.compile(r'\d{3}-\d{3}-\d{4}') mo = phoneNumRegex.search('My phone number is 333-333-2222.') print('Number is :' + mo.group()) # 输出:333-333-22222. 常用的匹配模式
2.1 利用括号进行分组;
import re phoneNumRegex = re.compile(r'(\d{3})-(\d{3}-\d{4})') # 使用括号,第一个括号内是第一组,第二个括号内是第二组; mo = phoneNumRegex.search('My phone number is 333-333-2222.') print('Number is :' + mo.group(0)) # 返回整个匹配文本;输出:Number is :333-333-2222 print('Number is :' + mo.group()) # group()中传入0,或者不传入,则返回整个匹配文本 print('Area Number is :' + mo.group(1)) # group()中传入1,返回第一个括号内的匹配值;输出:Area Number is :333 print('Phone Number is :' + mo.group(2)) # group()中传入2,返回第一个括号内的匹配值;输出:Phone Number is :333-2222 print(mo.groups()) # 使用gourps() 一次返回所有括号内的匹配结果;输出:('333', '333-2222') areaNum, ThoneNum = mo.groups() # 多重赋值技巧 print(areaNum, ThoneNum) # 输出:333 333-2222 phoneNumRegex = re.compile(r'(\(\d{3}\))-(\d{3}-\d{4})') # 当匹配值中有括号时,使用 \( 和 \) 进行转义; mo = phoneNumRegex.search('My phone number is (333)-333-2222.') print('Number is :' + mo.group()) # 输出:Number is :(333)-333-22222.2 使用管道符(|)匹配多个分组; | 相当于或运算;但只返回第一个匹配到的值;
import re HeroRegex=re.compile(r'batman|superman') # 匹配 batman 或者 superman; mo1=HeroRegex.search('batman and superman!') print(mo1.group()) # 输出管道符中第一个匹配项;输出:batman mo2=HeroRegex.search('superman and batman!') print(mo2.group()) # 输出管道符中第一个匹配项;输出:superman2.3 使用问号 (?) 实现可选匹配
使用 ? 表明?前面的分组是可选的,即匹配?前面的分组 零次 或者 一次,举例如下:
import re BatRegex=re.compile(r'bat(wo)?man') mo1=BatRegex.search('batman and batwoman') print(mo1.group()) mo2=BatRegex.search('batwoman and batman') print(mo2.group())2.4 用星号(*) 匹配零次,一次或者多次
使用 * 可以匹配 * 前面的分组零次,一次或者多次,举例如下:
import re BatRegex=re.compile(r'bat(wo)*man') mo1=BatRegex.search('batman and batwoman') print(mo1.group()) mo2=BatRegex.search('batwoman and batman') print(mo2.group()) mo3=BatRegex.search('batwowowowowowoman and batman') print(mo3.group())2.5 使用加号(+)匹配 一次 或者 多次;
使用加号 + 匹配+前面的分组 一次或者多次,若一次都没有出现,则匹配结果为None;
import re BatRegex=re.compile(r'bat(wo)+man') mo1=BatRegex.search('batman and batwoman') print(mo1.group()) mo2=BatRegex.search('batman') print(mo2==None) # 返回 True2.6 使用花括号 {} 匹配指定次数;
使用花括号{}, {3}前面的分组重复3次;{3,5} 前面的分组重复 3-5次;{3,}前面的分组3到无限大次;
import re BatRegex=re.compile(r'bat(wo){3}man') mo1=BatRegex.search('batman and batman') print(mo1==None) mo2=BatRegex.search('batwowowoman') print(mo2.group())2.7 贪心匹配 & 非贪心匹配
当{3,5},即匹配三次,四次,五次 都可以,那么 Python会匹配尽量多的次数,例如, Batwowowowowoman, 使用 BatRegex=re.compile(r'(wo){3,5}'),那么Python会自动匹配最多的次数,即wowowowowo, 那么如何可以匹配少的次数呢;我们使用问好(?),即BatRegex=re.compile(r'(wo){3,5}?') ,则返回wowowo;
import re BatRegex=re.compile(r'(wo){3,5}') mo1=BatRegex.search('batman and batwowowowowoman') print(mo1.group()) BatRegex2=re.compile(r'(wo){3,5}?') mo2=BatRegex2.search('batman and batwowowowowoman') print(mo2.group())3. Findall() 方法
Regex 的另一个方法是findall(),可以返回一组字符串,包含所有满足条件的匹配项;
正则表达式没有分组,则返回一个字符串列表;
正则表达式有分组,返回元组的列表,每个元组表示一个匹配;
import re phoneNumRegex=re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d') print(phoneNumRegex.findall('kai:199-1982-1222; Pi:178-1982-1223')) #返回 ['199-1982-1222', '178-1982-1223'] phoneNumRegex2=re.compile(r'(\d\d\d)-(\d\d\d\d-\d\d\d\d)') print(phoneNumRegex2.findall('kai:199-1982-1222; Pi:178-1982-1223')) #返回 [('199', '1982-1222'), ('178', '1982-1223')]4. 字符匹配
4.1 字符分类
''' \d 表示 0-9 的任何数字 \D 表示除了0-9 的任何字符 \w 表示任何字母,数字或者下划线字符 \w 表示除了 字母,数字 或者下划线 的字符 \s 表示 空格 制表符或者换行 \S 表示除 空格,制表符,换行之外的字符 '''4.2 建立自己的字符分类
使用上述字符分类大广泛的话,可以自定义字符分类,方法是使用 [],比如要匹配元音字母,使用[aeiouAEIOU],还可以使用 [0-5] 表示0到5的数字;并且 [] 中不需要使用\来取反义; 在[]最开始使用^ ,表示除 [] 中之外的字符;例如: [^AEIOUaeiou] ; 表示除 [aeiouAEIOU] 之外的字符;
4.3 插入字符和美元字符
可以在正则表达式开始的地方使用插入符号(^),表明匹配必须发生在被查找文本开始处。类似的 正则表达式最后使用 $, 表示文本结束;
举例: r'\d+$' 表示 从开始到结束都是数字的字符串。
import re phoneNumRegex=re.compile(r'^\d+$') print(phoneNumRegex.findall('1234567 345')==[]) # 无论是哪里有非数字的字符,都会返回[]; print(phoneNumRegex.findall('1234455'))4.4 通配字符
正则表达式中,. (句号)代表通配符, 匹配除了换行外的所有字符(只匹配一个字符);使用真正的. 需要使用转义(.); 通过传入 re.DOTALL 作为re.compile() 的第二个参数,可以使. 匹配所有字符,包括换行符;
import re noNewLineRegex=re.compile('.*') newLineRegex=re.compile('.*',re.DOTALL) mo=noNewLineRegex.search('So ,god bless American.\n God do not bless American.') mo1=newLineRegex.search('So ,god bless American.\n God do not bless American.') print("----") print(mo.group()) print("----") print(mo1.group())4.5 点星(.*)符号
使用 .* 代表任意字符;
import re nameRegex=re.compile(r'first name:(.*) last name:(.*)') mo=nameRegex.search('first name:zhang last name: Kai') print(mo.group()) # 返回:first name:zhang, last name: Kai贪心模式 & 非贪心模式(使用?)
import re nonGreedyRegex=re.compile(r'<.*?>') # 非贪心模式 GreedyRegex=re.compile(r'<.*>') # 贪心模式 mo=nonGreedyRegex.search('<first name:zhang> last name: Kai>') mo2=GreedyRegex.search('<first name:zhang> last name: Kai>') print(mo.group()) # 返回:<first name:zhang> print(mo2.group()) #返回:<first name:zhang> last name: Kai>5. 第二参数 re.I
RE.compile()的第二参数;
6. 正则表达式命名分组
命名方式: ?P<名称> 举例:(?P<year>\d{4}) 匹配一个四位数字,名字为year;