first:正则表达式手册
妖怪:
? | 1)匹配前面的子表达式零次或一次。例如,“ 2)当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“ |
---|
字符:'. ' 英文...表示省略,即无穷无尽的内容,而单个'.'即表示匹配任意单个字符(除“\
n
”之外)
'\s' -->space 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]
‘^’和'[^a-z]','[^xyz]'中'^'不同,前者代表位置,后者有相反的意思
测试正则表达式代码:
import re p = re.compile('^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$') n = 0 flag = 1 while flag: content = input("请输入测试内容:") test = p.findall(content) if test: print('测试匹配成功: ', test) flag = 0 else: n += 1 print('第%d输入错误,请重新测试' % n)
注意:'\' 具有剥夺原字符的特殊功能
'\'使得普通字符具有特殊能力
‘\’: 1将一个普通字符变成特殊字符,例如\d表示匹配所有的十进制数字
2.解除元字符的特殊功能,例如\.表示匹配点号本身
3.引用序号对应的子组所匹配的字符串
import re print(re.search(r'FishC', 'I love FishC.com!')) print(re.match(r'FishC', 'FishC.com!')) print(re.search(r'\.', 'I love FishC.com!')) print(re.search(r'\d\d', 'I love 12345 FishC.com!')) #创建字符类[],匹配到任意一个都算成功,[.]内都转换为普通字符 print(re.search(r'[aeiouAE]', 'I love 12345 FishC.com!')) print(re.search(r'[2-9]', 'I love 12345 FishC.com!')) print(re.findall(r'[a-z]', 'FishC.com')) print(re.findall(r'[\n]', 'FishC.com\n')) #脱字符,放在后面将只是普通字符 print(re.findall(r'[^a-z]', 'FishC.com\n')) print(re.findall(r'[a-z^]', 'FishC.com^\n')) #限定匹配的次数{},内部不要加空格 print(re.search(r'ab{3}c', 'aaabbbcdeee')) print('flag==0') print(re.search(r'ab{3, 5}c', 'aaabbbcdeee')) print(re.search(r'ab{3,6}c', 'aaabbbbbcdeee')) print(re.search(r'(ab){3,6}c', 'aabababcdeee')) print(re.search(r'[01]\d\d|2[0-4]\d|25[0-5]', '188')) #匹配Ip地址,发现问题 print(re.search(r'(([01]{0, 1}\d{0, 1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0, 1}\d{0, 1}\d|2[0-4]\d|25[0-5])', '192.168.1.1')) #\后面加的数字 1.数字是1-99,表示引用序号对应的子组所匹配的字符串 2.数字是0或者3位数字,它是八进制表示的ascii值对应的字符 print(re.search(r'(FishC)\1', 'FishC.com')) #r'(FishC)\1 == rFishCFishC print(re.search(r'(FishC)\1', 'FishCFishC')) print(re.search(r'(FishC)\060', 'FishCFishC')) #0的ascii为30对应的八进制为60,八进制需要三位表示 print(re.search(r'(FishC)\060', 'FishCFishC0')) print(re.search(r'(FishC)\141', 'FishCFishCa')) #贪婪模式 s = '<html><title>I love python</title></html>' print(re.search(r"<.+>", s)) print(re.search(r"<.+?>", s))
import re #\b匹配一个单词边界,单词被定义为Unidcode的字母数字或下横线字符 print(re.findall(r'\bFishC\b', 'FishC.com!FishC_com!(FishC)')) print(re.findall(r'\s', '\n\t\f\v ')) print(re.findall(r'\w', '我爱鱼C工作室( Love_FishC.com)')) #通常匹配一个单词边界,自有在字符类中才表示'退格' #编译正则表达式 p = re.compile(r'[a-z]') print(type(p)) print(p.search("I love python")) #findall前面是模块方法,这里是模式对象方法 print(p.findall("I love python")) #编译标志(flags=0) charref =re.compile(r""" @[#] #开始数字引用 ( 0[0-7]+ #八进制格式 |[0-9]+ #十进制格式 |x[0-9a-fA-F]+ ) ; #结尾分号 """, re.VERBOSE) charref =re.compile("@#(0[0-7]+|[0-9]+|x[0-9a-fA-F]+);")
执行结果如下:
['FishC', 'FishC']
['\n', '\t', '\x0c', '\x0b', ' ']
['我', '爱', '鱼', 'C', '工', '作', '室', 'L', 'o', 'v', 'e', '_', 'F', 'i', 's', 'h', 'C', 'c', 'o', 'm']
<class 're.Pattern'>
<re.Match object; span=(2, 3), match='l'>
['l', 'o', 'v', 'e', 'p', 'y', 't', 'h', 'o', 'n']
import re print(re.search(r" (\w+) (\w+)", "I love FishC.com")) #re.Match object模块匹配对象,不是返回字符串,对象有一些方法,使用这些方法就行 print(re.search(r". (\w+) (\w+)", "I love FishC.com").group()) #如果正则表达式中有词组,可用group进行词组捕获 result = re.search(r". (\w+) (\w+)", "I love FishC.com") print(result.group(1)) print(result.start(1)) print(result.end(1)) print(result.span()) print(result.span(1))
执行结果如下:
<re.Match object; span=(1, 12), match=' love FishC'>
I love FishC
love
2
6
(0, 12)
(2, 6)
second: re模块中常用功能函数
1、compile()
如果你需要重复地使用某个正则表达式,那么你可以先将该正则表达式编译成模式对象
编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,提高效率。)
格式:
re.compile(pattern,flags=0)
pattern: 编译时用的表达式字符串。
flags 编译标志位,用于修改正则表达式的匹配方式,常用的flags有:
标志 |
含义
|
re.S(DOTALL)
| 使.匹配包括换行在内的所有字符 |
re.I(IGNORECASE)
|
使匹配对大小写不敏感
|
re.L(LOCALE)
|
做本地化识别(locale-aware)匹配,法语等
|
re.M(MULTILINE)
|
多行匹配,影响^和$
|
re.X(VERBOSE)
|
该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
|
re.U
|
根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B
|
import re tt = "Tina is a good girl, she is COOL, clever, and so on..." rr = re.compile(r'\w*oo\w*',re.I) print(rr.findall(tt)) #查找所有包含'oo'的单词 执行结果如下: ['good', 'COOL']
2、match()
决定re是否在字符串刚开始的位置匹配。
//注:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'
格式:re.match(pattern, string, flags=0)
区别:rx.match(string[,pos[,endpos]])
import re print(re.match('com', 'comwww.runcomoob').group()) try: re.match('com$', 'comwww.runcomoob').group() except Exception as e: print("未匹配到:", e) 执行结果如下: com 未匹配到: 'NoneType' object has no attribute 'group'
3、search()
格式:re.search(pattern, string, flags=0)
区别:regex.search(string[,pos[,endpos]])
re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
import re print(re.search('\dcom','www.4comrunoob.5com').group()) 执行结果如下:
4com
//注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
- group() 返回被 RE 匹配的字符串
- start() 返回匹配开始的位置
- end() 返回匹配结束的位置
- span() 返回一个元组包含匹配 (开始,结束) 的位置
- group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
a. group() 返回re整体匹配的字符串,
b. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
c.groups() 方法groups()返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。
import re a = "123abc456" print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)) #123abc456,返回整体 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)) #123 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)) #abc print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)) #456 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups()) #('123', 'abc', '456') 执行结果如下: 123abc456 123 abc 456 ('123', 'abc', '456')
finally:小试牛刀
1)判断字符串是否是全部小写
import re s1 = 'adkkdk' s2 = 'abcefg'
an = re.search('[a-z]+$', s1) if an: print('s1:', an.group(), '全为小写') else: print(s1, "不全是小写!")
an = re.match('[a-z]+$', s2) if an: print('s2:', an.group(), '全为小写') else: print(s2, "不全是小写!")
执行结果如下:
s1: adkkdk 全为小写
s2: abcefg 全为小写
2) 正则表达式习题
总结:1)返回一个对象,就可以调用相应的方法,通过help(object)查询相应的方法。
re.findall不同 p.findall
2)re模块基本函数参数大部分都是(pattern,string[, flags = 0])
3)匹配任何不在指定范围内的任意字符 [^a-z]+$ 非^[a-z]+$