python正则表达式和小练习

达到文本匹配的目的
import re
所有的元字符都只能匹配一个字符

代码说明
.匹配除换行符外任意一个字符
[abc]字符集合,只能表示一个字符位置。匹配所包含的任意一个字符
[^abc]字符集合,只能表示一个字符位置。匹配除去集合内字符的任意一个字符
\s匹配1位空白字符,包括换行符、制表符、空 格 [ \f\r\n\t\v]
a\t查找 a挨着\t (没有中括号)
\d0-9]匹配1位数字
\w匹配[a-zA-Z0-9_],包括中文的字
\W匹配除\w之外的字符

重复

代码说明
*表示前面的正则表达式会重复0次或多次
+表示前面的表达式重复至少1次
表示前面的正则重复0次或者1次
{n}重复固定的n次
{n},重复至少n次
{n,m}重复n 到m次
x竖线y匹配 x 或者y
{n,m}重复n 到m次
(pattern)使用小括号指定一个子表达式,也叫分组 捕获后会自动分配组号从1开始 可以改变优先级
\数字匹配对应的分组
(?=exp)零宽度正预测先行断言 断言exp一定在匹配的右边出现,也就是说断 言后面一定跟个exp
(?<=exp)零宽度正回顾后发断言 断言exp一定出现在匹配的左边出现,也就是 说前面一定有个exp前缀
(?!exp)零宽度负预测先行断言 断言exp一定不会出现在右侧,也就是说断言 后面一定不是exp
(?<!exp)零宽度负回顾后发断言 断言exp一定不能出现在左侧,也就是说断言 前面一定不能是exp

小例子:用零宽断言取出 finished going done doing 里面以ing结尾的的 go 和 do
import re s = 'finished going done doing' ss = re.compile(r'\b\w+(?=ing\b)', re.M) ret = ss.findall(s) print(ret)
``

import re 模块下的模式:

在默认模式下,无论敲多少行都是只有一行。注意 . 不能匹配换行符 \n
单行模式,无视 换行符 一点 . 足够贪婪 re.S
多行模式,没有修改.的行为,遇到换行符不匹配 。有换行符 re.S
单行多行模式同时勾选的时候有 . 则贪婪 无点则多行,影响行首和行尾
使用 | 位或 运算开启多种选项
例如 :re.S | re.S

编译模式
re.compile(pattern, flags=0)
pattern表示编译的模式方法,则返回正则表达式regex,多用compoile可以提高效率

单次匹配

re.match(pattern, string, flags=0)
regex.match(string[, pos[, endpos]])
match匹配从字符串的开头匹配,regex对象match方法可以重设定开始位置和结束位置。返回match对象。

re.search(pattern, string, flags=0)
regex.search(string[, pos[, endpos]])
从头搜索直到第一个匹配,regex对象search方法可以重设定开始位置和结束位置,返回match对象

编译过程:

import re
s = """bottle\nbag\nbig\napple"""
for i, c in enumerate(s, 1):
    print((i-1, c), end = '\n' if i %10 == 0 else ' ')
print()
#  match方法
result = re.match('b', s) #  找到一个b 就返回
print(1, result)
result = re.match('a', s )
print(2, result) #  没找到 返回none
result = re.match('^a' , s , re.M) #  多行模式从头开始找
print(3,result)
result = re.match('^a' , s , re.S) #  单行模式从头开始找
print(4,result)
#  先编译
regex = re.compile('a')
result = regex.match(s) #  从头开始找
print(5, result)
result = regex.match(s, 15) #  从15d的索引开始找
print(6, result)

#search
result = re.search('a', s) #  扫描找到的匹配的第一个位置
print(7, result)
regex = re.compile('b')
result = regex.search(s) #  默认从开头开始找
print(8, result)
result = regex.search(s, 1) #  从第二个开始找,不是跳到第二个b的意思
print(9, result)
regex = re.compile('^b', re.M) #不管模式 找到就返回
result = regex.search(s,8)
print(10,result)

#fullmatch 整个字符串和正则表达式匹配
result = re.fullmatch('bag', s)
print(11, result)
regex = re.compile('bag')
result = regex.fullmatch(s)
print(12, result)
result = regex.fullmatch(s, 7)
print(13, result)
result = regex.fullmatch(s, 7, 10) # 要完全匹配 多了少了都不行
print(14, result)

全文搜索

re.findall(pattern, string , flags = 0)
regex.findall(string )
对整个字符串,从左至右匹配,返回所有匹配项的列表
re.finditer(pattern, string , flags = 0)
regex.findall(string )
对整个字符串,从左至右匹配,返回所有匹配项,返回迭代器。 注意每次迭代返回的是match对象

import re
s = """bottle\nbag\nbig\napple"""
for i, c in enumerate(s, 1):
    print((i-1, c), end = '\n' if i %10 == 0 else ' ')
print()
#  findall方法
result = re.findall('b', s)
print(1, result) #  以列表形式返回所有匹配到的项
regex = re.compile('^b') #  以b为开头
result = regex.findall(s)
print(2, result) #  找到一个就返回
regex = re.compile('^b', re.M) #  多行模式下的查找
result = regex.findall(s, 7)
print(3,result) #  两个b
regex = re.compile('^b', re.S)
result = regex.findall(s)
print(4, result) #  单行模式下查找第一个
regex = re.compile('^b', re.M)
result = regex.findall(s, 7, 10)
print(5, result)

# finditer方法
result = regex.finditer(s) #返回一个迭代器
r = next(result)
print(type(r), r) # match对象
print(r.start(), r.end(), s[r.start():r.end()])
r = next(result) # 下一个,迭代完就没了
print(type(r), r) 
print(r.start(), r.end(), s[r.start():r.end()]) #  取到位置和match

匹配替换

re.sub(pattern, replacement, string, count=0, flags=0)
regex.sub(replacement, string, count=0)
使用pattern对字符串string进行匹配,对匹配项使用repl替换。 replacement可以是string、bytes、function
re.subn(pattern, replacement, string, count=0, flags=0)
regex.subn(replacement, string, count=0)
可以看到替换了多少次

import re
s = """bottle\nbag\nbig\napple"""
for i, c in enumerate(s, 1):
    print((i-1, c), end = '\n' if i %10 == 0 else ' ')
print()
#  替换方法
regex = re.compile('b\wg')
result = regex.sub('magedu', s)
print(1, result) #  被替换后的字符串
result = regex.sub('magedu', s ,1) # 替换一次
print(2, result)

regex = re.compile('\s+')
result = regex.subn('\t', s)#  被替换后的字符串和替换次数
print(3, result) 

分割字符串

re.split (pattern, string, maxsplit=0, flags=0)
不能指定多个字符进行分隔

import re
s = """
os.path.abspath(path)
normpath(join(os.getcwd(), path)).
"""
#  把每行单词提取出来
regex = re.compile('\W+')
result = regex.split(s)[1:][:-1]
print(result)

分组

如果pattern中使用了分组,如果有匹配的结果,会在match对象中

  1. 使用group(N)方式返回对应分组,1到N是对应的分组,0返回整个匹配的字符串,N不写缺省为0
  2. 如果使用了命名分组,可以使用group(‘name’)的方式取分组
  3. 也可以使用groups()返回所有组
  4. 使用groupdict() 返回所有命名的分组
import re
s = '''bottle\nbag\nbig\napple'''
for i,c in enumerate(s, 1):
    print((i-1, c), end='\n' if i%10==0 else ' ')
print()

#  分组
regex = re.compile('(b\w+)')
result = regex.match(s) #  从头匹配一次
print(type(result))
print(1,'match',result.groups())
result = regex.search(s, 1) #  从指定位置向后匹配一次
print(2,'search', result.groups())

#  命名分组
regex = re.compile('(b\w+)\n(?P<name2>b\w+)\n(?P<name3>b\w+)')
result = regex.match(s)
print(3, 'match', result)
print(4, result.group(3), result.group(2), result.group(1))
print(5, result.group(0).encode()) # 0 返回整个匹配字符串
print(6, result.group('name2'), result.group('name3'))
print(7, result.groups())# 返回一个元组
print(8, result.groupdict())# 返回一个字典,key为上面的名字

result = regex.findall(s)
print(result) # 返回一个列表
for x in result:
    print(type(x),x) # 返回一个元组

regex = re.compile('(?P<head>b\w+)')
result = regex.finditer(s) # 生成一个迭代器
# print(result)
for x in result:
    print(type(x), x, x.group(), x.group('head')) # group全部都提取 提取分组名

(考虑不周,或者有更多的想法,尽情评论)
练习:
1.校验密码强度
密码的强度必须是包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间

测试文本
rlgCmSol9N
g1oI8JSrE
wcSnCrUO
QCHAzSiJ
EFSOSCPH
x53rKua
NFL0PWVJ

^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}

regax = re.compile(’^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}’, re.M)
result = regax.findall(passwd)
print(result)

2.匹配ip地址:

简单组合ip
192.168.1.150
0.0.0.0
255.255.255.255
17.16.52.100
172.16.0.100
400.400.999.888
001.022.003.000
257.257.255.256
19231212123211
不考虑具体实现的简单的匹配

^(\d{1,3}.){3}(\d{1,3})$
考虑ip地址组成和通过网上直接查找ip得到较为准确的匹配
((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[1-4]\d|25[0-5]|[01]?\d\d?)

3.表达式匹配几种格式的电话号码,
像(010)88886666,或022-22334455,或02912345678等。
我们对它进行一些分析吧:首先是一个转义字符
(,它能出现0次或1次(?),然后是一个0,
后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

(?0\d{2}[) -]?\d{8}

(0\d{2})[- ]?\d{8}|0\d{2}[- ]?\d{8}
这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,

4.匹配美国的邮政编码

\d{5}-\d{4}|\d{5}

5.匹配以ing结尾的单词的前面部分(除了ing以外的部分),
如查找I’m singing while you’re dancing.

\b\w+(?=ing\b)

6.匹配一个0~999之间的任意数字

1
12
995
9999
102
02
003
4d

方法一:\d?(\d\d)|[14]
方法二:[0-9]?[0-9]?[0-8]
方法三:^([1-9]\d\d?|\d)(?!\d)

7、选出含有ftp的链接,且文件类型是gz或者xz

las=’’‘ftp://ftp.gmplib.org/pub/gmp-5.1.2/gmp-5.1.2.tar.xz
ftp://ftp.vim.org/pub/vim/unix/vim-7.3.tar.bz2
http://anduin.linuxfromscratch.org/sources/LFS/lfs-packages/conglomeration//iana-etc/iana-etc-
2.30.tar.bz2
http://anduin.linuxfromscratch.org/sources/other/udev-lfs-205-1.tar.bz2
http://download.savannah.gnu.org/releases/libpipeline/libpipeline-1.2.4.tar.gz
http://download.savannah.gnu.org/releases/man-db/man-db-2.6.5.tar.xz
http://download.savannah.gnu.org/releases/sysvinit/sysvinit-2.88dsf.tar.bz2
http://ftp.altlinux.org/pub/people/legion/kbd/kbd-1.15.5.tar.gz
http://mirror.hust.edu.cn/gnu/autoconf/autoconf-2.69.tar.xz
http://mirror.hust.edu.cn/gnu/automake/automake-1.14.tar.xz
ftp//xz’’’

redus = re.compile('ftp.+[gz|xz]$', re.M)
res = redus.findall(urls)
for i in res:
	print(re.split('[/]', i)[-1])

8、身份证匹配
321105700101003
321105197001010030
11210020170101054X
00121323123123123C
440902199312010430
11210020170801054X
17位数字+1位校验码组成 前6位地址码,8位出生年月,3位数字,1位校验位(0-9或X


^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$
匹配:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|(3[0-1]))\d{3}([0-9]|X)$

9.匹配邮箱地址
-ip@daddf.com
web.ddfda@adfsd.com.cn
super.user@google.com
a@w-a-com


\w+[-.\w]*@[\w-]+(\.[\w-]+)+

10、html提取

<a href='http://www.baidu.com/index.html' target='_blank'>百度</a>
<[^<>]+>(.*)<[^<>]+>

11.匹配图片
<img src="([^"]+.jpg)"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值