Python学习杂记_15_正则表达式

正则表达式

正则表达式就是用来查找字符串的,它能够查找规则比较复杂的字符串。
使用正则表达式首先要导入re模块
import re

s = "besttest is good!besttest best"
print(re.match(r'best',s))
# 返回对象为 <_sre.SRE_Match object; span=(0, 8), match='besttest'>
# match方法接收3个参数,第一个是匹配的规则(待匹配的样本字符串),也就是正则表达式;
# 第二个是被检查的字符串;
# 第三个参数不是必填的,用于控制正则表达式的匹配方式,看下面正则表达式的匹配模式。
# match方法是从字符串的“第一个单词”中匹配字符串,如果匹配到返回一个对象,如果匹配不到,则返回None

print(re.search(r'is',s))
# 返回对象为 <_sre.SRE_Match object; span=(9, 11), match='is'>
# search方法的参数和match一样,不一样的是,match是从字符串开头第一个词匹配,只看开头,
# 而search方法则是从字符串的整个内容里面找,如果找到了就返回第一个,找不到就返回None。
# 如过想列出找到的内容需要用.group()方法 print(re.search(r'is',s).group()),这样结果就是is

# 注意到了吗?在正则表达式的前面我加了一个‘r’,它代表按字符原样来匹配,否则当表达式字符串中包含转义自如的话就会被转义

print(re.findall(r'best',s))
# findall方法的参数和 match、search 一样,不一样的是,findall 是从字符串所有内容里找,找到就返回,直到找完。
# findall 方法返回的是一个列表,而且直接返回,直接print就可以看到,不用group()方法。

print(re.sub(r'best','BEST',s))
# sub 方法和字符串的replace方法一样,是用来替换字符串的;
# 用正则表达式身后的字符串替换正则表达式的字符串;
# 会返回一个新的整个字符串,如果匹配不到的话,返回原来的字符串。

数量词
要与findall方法联合使用

星号 *
# 匹配星号*前面的一个字符0次或多次,仅仅是*号前的一个字符。
print(re.findall(r'a*b','ab a abbbbbb b'))
结果是 ['ab', 'ab', 'b', 'b', 'b', 'b', 'b', 'b']

加号 +
# 匹配加号+前面的一个字符1次或多次,仅仅是+号前面的一个字符。
print(re.findall(r'st+','besttest is best s'))
结果是 ['stt', 'st', 'st']

问号 ?
# 匹配问号?前面的一个字符0次或1次,仅仅是?号前面的一个字符。
print(re.findall(r'st?','besttest is best'))
结果是 ['st', 'st', 's', 'st']

指定匹配次数 {n}
# 匹配花括号前面的一个字符n次,仅仅是花括号前面的一个字符。
print(re.findall(r't{3}er', 'besttest is best lettter letter'))
结果是 ['ttter']

指定匹配次数的范围 {m,n}
# 匹配花括号前面的一个字符m到n次,仅仅是花括号前面的一个字符。
print(re.findall(r't{1,3}er', 'besterst is best lettter letter'))
结果是 ['ter', 'ttter', 'tter']


一般字符

'.' # 默认匹配除\n之外的任意一个字符
print(re.findall(r'b.','besttest is good ba bf bo'))
结果: ['be', 'ba', 'bf', 'bo']

'\' # 转译符,前面的* + ?这样的字符都有特殊含义了,如果你就是想找它的话,那就得转译了
# 意思就是说如果你想让特殊字符失去以前的含义,那么就得给它前面加上'\'
print(re.findall(r'\?','besttest is best????'))
结果: ['?', '?', '?', '?']

'|' # 匹配|左或|右的字符
print(re.findall(r'best|is','besttest is best'))
结果: ['best', 'is', 'best']

'[]' # 字符集合,里面是某些字符的集合,匹配的时候是这个集合里面的任意一个就可以
print(re.findall(r'be[stacj]','besttest is best bejson bed'))
结果: ['bes', 'bes', 'bej']
# 在[]里面如果用^的话代表取反,也就是不包括的这些字符串的
print(re.findall(r'be[^stac]','besttest is best bejson'))
结果: ['bed']


边界匹配

'^' # 数字6的上键位,它代表匹配以什么字符串开头,多行情况下匹配每一行的开头。
print(re.findall(r'^b','besttest is good\nbestest',re.M))
print(re.findall(r'^http://','http://www.baidu.com is good\nbestest'))
结果: ['b', 'b'] 和 ['http://']

'$' # 匹配以什么字符结尾,多行情况下匹配每一行的结尾;
# 多行时是从最后一行开始匹配。
print(re.findall(r'd$','besttest is good'))
print(re.findall(r'\.jpeg$|\.gif$|\.png$','touxiang.png\nabc.gif',re.M))
结果: ['d'] 和 ['.png', '.gif']

'\A' # 仅以什么字符开头,和^不同的是它不能用多行模式。
print(re.findall(r'\Ahttp://','http://www.baidu.com is good\nhttp://www.sohu.com',re.M))
print(re.findall(r'\Ab','besttest is good'))
结果:['http://'] 和 ['b']

'\Z' # 仅以什么字符结尾,和$不同的是它不能用多行模式;
# 在多行时,是从最后一行开始匹配。
print(re.findall(r'\.jpeg\Z|\.png\Z|\.gif\Z','touxiang.png\nqq.gif\nabc.jpeg',re.M))
结果: ['.jpeg']


预定义字符集合


'\d' # 匹配数字0-9
print(re.findall(r'\d+','sdf2342312sdfs342332sdf'))
结果: ['2342312', '342332']
print(re.findall(r'\d','sdf2342312sdfs342332sdf'))
结果: ['2', '3', '4', '2', '3', '1', '2', '3', '4', '2', '3', '3', '2']

'\D' # 匹配非数字
print(re.findall(r'\D+','sdf2342312sdfs……&()'))
结果: ['sdf', 'sdfs……&()']
print(re.findall(r'\D','sdf2342312sdfs……&()'))
结果: ['s', 'd', 'f', 's', 'd', 'f', 's', '…', '…', '&', '(', ')']

'\w' # 匹配[A-Za-z0-9],也就是所有的字母和数字和中文
print(re.findall(r'\w+','sdf234%^2312sdfs&你好你好'))
结果: ['sdf234', '2312sdfs', '你好你好']

'\W' # 匹配不是[A-Za-z0-9],也就是不是字母、数字和中文字符的字符串
print(re.findall(r'\W+','sdf234%^2312sdfs&你好你好!。。'))
结果: ['%^', '&', '!。。']

'\s' # 匹配空白字符如 \t、\n、\r,空格
print(re.findall('\s','axss\n\tsdf\t\r\t sdfsd sdf '))
结果: ['\n', '\t', '\t', '\r', '\t', ' ', ' ', ' ']

'\S' # 匹配非空白字符,不是\t、\n、\r,空格
print(re.findall('\S+','axss\n\tsdf\t\r\t sdfsd sdf '))
结果: ['axss', 'sdf', 'sdfsd', 'sdf']

[A-z]大小写字母
[a-z]#小写字母
[A-Z]#大写字母
[0-9]#所有的数字

print('new_str:',new_str)
print(re.findall(r'[A-Z]',new_str))
print(re.findall(r'[a-z]',new_str))
print(re.findall(r'[0-9]',new_str))

插播程序栗子:

需求: 生成制定个数的 8位字符串,每个字符串必须包含大写字母、小写字母和数字,
把这些字符串保存在名为password的文件里。

import re,string,random

sub_str = string.ascii_letters + string.digits
fw = open('passwd','w')
def passwds(n):
count = 0
while count<n:
new_str = ''.join(random.sample(sub_str, 8))
if re.search(r'[A-Z]', new_str) and \
re.search(r'[a-z]', new_str) and \
re.search(r'[0-9]', new_str):
fw.write(new_str+'\n')
count+=1
passwds(5)

分组匹配

'(...)' # 分组匹配,把某些规则写成在一个括号括起来的组里,这样就可以直接对这个组进行一些匹配了。
# 举个例子,如果要匹配ip地址的话,
# ip地址是类似这样的 192.168.5.1 每一段都是1位到3位的数字,数字后面有个隔点,
# 正常写的话,要这样写正则匹配:
# print(re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',"192.168.1.3"))
# >>> ['192.168.1.3']
# 这样写有点麻烦了,从ip地址我们可以发现规律,除了第一段,之后的每段都是'.\d{1,3}',1到3个数字,
# 写重复的代码是低级的,这样的话就可以用分组来简化上面写的正则匹配,
# 把'.\d{1,3}'当做一个整体,然后让它出现3次就ok了,可以改成如下的样纸:
# print(re.search(r'\d{1,3}(\.\d{1,3}){3}',"192.168.1.3").group())
# 这里用了search方法,结果和上面的一样:
# >>> 192.168.1.3
# 如果用findall方法:
# print(re.findall(r'\d{1,3}(\.\d{1,3}){3}',"192.168.1.3"))
# 发现结果是下面这样的,不是我们想要的,
# >>> ['.3']
# 为啥会这样呢,用match方法和search方法都是正常的,findall方法这里有个坑:
# 就是如果findall方法里面有分组的话,默认结果就只是分组里面的内容,也就是匹配到小括号里面的内容,
# 如果想让结果正确的话就在分组最前面写上'?:',一个问号和一个冒号就可以了,启用“不捕捉模式”
# print(re.findall(r'\d{1,3}(?:\.\d{1,3}){3}',"192.168.1.3"))
# >>> 192.168.1.3

# findall方法里面有分组的话,默认结果就只是分组里面的内容
# findall方法里面有分组的话,默认结果就只是分组里面的内容
# findall方法里面有分组的话,默认结果就只是分组里面的内容
posted @ 2017-06-22 16:24  后知者  阅读(361)  评论(0编辑  收藏  举报