15_python笔记-正则表达式


博客cpen_web

练习1

1、实现九九乘法表
2、实现1-100之和
3、如何跨模块共享变量
4、python中生成随机整数(1-10),随机小数(1-10),0-1随机小数的方法
5、python中哪些是可变数据类型,哪些是不可变数据类型,为什么
6、统计字符串中每个字符出现的次数
7、python实现,给定一个字符串,找到字符串中第一个重复的字符
8、重复接受一个用户输入的字符,如果是正整数,就输出结果,否则就一直输入
9、用python实现冒泡排序

1、实现九九乘法表

def lx01():  # 九九乘法表
    for i in range(1, 10):							# 注:range(1, 10) --> 1...9
        for j in range(1, i + 1):						# 注:range(1, i + 1) --> 1...i
            print(f"{j}*{i}={j * i}", end=" ")			# 注:end指定结尾字符串
        print()									# 注:print默认输出换行符

2、实现1-100之和

方法1

def lx02():  # 累加
    nub = 0
    for i in range(100):
        i += 1
        nub += i
    print(nub)

方法2

print(sum(list(range(1,101))))		# 注:range(1,101)直接转换成列表使用sum进行求和
				# 注:range是可迭代对象

3、如何跨模块共享变量

使用导入这个文件,调用文件里的变量,可以实现跨模块共享

4、python中生成随机整数(1-10),随机小数(1-10),0-1随机小数的方法

def lx04():  # 随机数
import random
    print(random.randint(1, 10))				# 注:生成随机整数的范围
    print(random.uniform(1, 10))				# 注:生成随机小数的范围
    print(random.random())					# 注:生成0-1随机小数的范围

5、python中哪些是可变数据类型,哪些是不可变数据类型,为什么

# 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,就称不可变数据类型
# 包括:int(整型)、string(字符串)、tuple(元组)
# 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,就称可变数据类型
# 包括:set(集合)、list(列表)、dict(字典)

6、统计字符串中每个字符出现的次数

def lx06():  # 统计次数
    str_1 = input("请输入字符串: ")
    for i in set(str_1):							# 注:对str进行set集合去重
        print(f"字符{i}出现了{str_1.count(i)}次")

7、python实现,给定一个字符串,找到字符串中第一个重复的字符

def lx07():  # 找第一个重复字符
    str_1 = input("请输入字符串: ")
    for i in str_1:
        if str_1.count(i) > 1:
            print(f"第一个重复的字符为{i}")
            return								# 注:大于1时直接return退出函数

8、重复接受一个用户输入的字符,如果是正整数,就输出结果,否则就一直输入

def lx08():
    while True:
        str_1 = input("请输入: ")
        if str_1.isdigit():							# 注:str isdigit 判断是不是只有数字
            print(str_1)
        else:
            print("你输入的不是正整数,退出程序")
            return

9、用python实现冒泡排序

def lx09():
    list_1 = [46,45,13,78,65,99,45]
    n = len(list_1)

    # 遍历所有数组元素
    for i in range(n):
        for j in range(0, n - i - 1):
            if list_1[j] > list_1[j + 1]:
                list_1[j], list_1[j + 1] = list_1[j + 1], list_1[j]
    print(f"排序后的数组为{list_1}")
def bubbleSort(arr):
    n = len(arr)
    # 遍历所有数组元素
    for i in range(n):
        # Last i elements are already in place
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

arr = [64, 34, 25, 12, 22, 11, 90]
bubbleSort(arr)
print("排序后的数组:")
for i in range(len(arr)):
    print("%d" % arr[i])

示例:冒泡排序的改进 引入标志位 判定某件事情是否发生

list1 = [1,4,6,2,5,3,9,7,8]
length = len(list1) - 1
i = j = 0
while i < length:
    flag = 1		# 注:标志位
    print(f"第{i+1}次,list:{list1}")
    j = 0
    while j < length - i:
        if list1[j] > list1[j + 1]:
            list1[j],list1[j + 1] = list1[j + 1],list1[j]
            flag = 0        # 注:有交换的情况下 flag = 0
        j += 1
    if flag:                # 注:if flag  flag=1的时候 break退出
        break
    i += 1
print(list1)

第1次,list:[1, 4, 6, 2, 5, 3, 9, 7, 8] # 注:改进后 只需要排序4次
第2次,list:[1, 4, 2, 5, 3, 6, 7, 8, 9]
第3次,list:[1, 2, 4, 3, 5, 6, 7, 8, 9]
第4次,list:[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Python里交换数值

>>> a = 1
>>> b = 2
>>> a
1
>>> b
2
>>> a, b = b, a
>>> a
2
>>> b
1

练习2

1、循环接收键盘输入的字符,判定是否属于正整数、负整数、浮点数 ,并给出相应提醒 按exit退出

while True:
    import re
    num = input("请输入:")
    if re.findall(r"^\+?[1-9]\d*$",num):
        print("正整数")
    elif re.findall(r"^\-[1-9]\d*$",num):
        print("负整数")
    elif re.findall(r"^[\+|\-]?\d+\.\d+$",num):
        print("浮点数")
    elif num == "exit":
        break
    else:
        print("重新输入")

2、验证密码是否合法,密码要求8-10位,以(字母或者下划线开头),给出相应提示

import re
passwd = input("请输入:")
if re.findall("^[A-Za-z_].{7,9}$",passwd):
    print("密码合法")
else:
    print("密码不合法")

3、提取电话号码

wen tel: 17375722991
wen tel: 173-7572-2992
wen tel: 173 7572 2993
wen tel: (+86) 17375722994

format1 = input("请提取出你输入的格式:")
import re
ret = re.search("(\(\+86\))?1\d{2}([ \-]?\d{4}){2}",format1)
print("打印:",ret)

#注:分组向后引用 ret = re.search(r"1\d{2}([ \-]?)\d{4}\1\d{4}",format1)   # 注:进行分组向后引用

请提取出你输入的格式:12345678901
打印: <re.Match object; span=(0, 11), match=‘12345678901’>
请提取出你输入的格式:123-4567-8901
打印: <re.Match object; span=(0, 13), match=‘123-4567-8901’>
请提取出你输入的格式:123 4567 8901
打印: <re.Match object; span=(0, 13), match=‘123 4567 8901’>
请提取出你输入的格式:(+86)12345678901
打印: <re.Match object; span=(0, 16), match=’(+86)12345678901’>

知识点3 正则分组

正则分组-简单分组

当使用分组时,除了可以获得整个匹配,还能够获得选择每一个单独组,使用 () 进行分组

简单分组

分组不匹配(?:规则)
· 表示将()仅用于组合字符串,不识别为分组

正则分组-命名分组

命名分组:(?P规则)

正则分组-引用分组
引用分组:
·使用()分用,用\0, \1, \2引用 (\0表示匹配的整个串)

示例1:正则分组

#正则分组
import re
ret = re.search(r'(\d{3})-(\d{3})-(\d{3})',"123-321-234abc") # 注:数字匹配3次 作为1个分组
print(ret.group())      # group正则表达式能获得的所有对象
#结果为 123-321-234
print(ret.group(0))     # 0代表所有匹配的字符,不接参数 默认为0
#结果为 123-321-234
print(ret.group(1))     # 1代表第1个组 获取第1个分组
#结果为 123
print(ret.group(2))     # 2代表第2个组
#结果为 321
print(ret.group(3))     # 3代表第3个组
#结果为 234
#print(ret.group(4))
#注:报错 IndexError: no such group

#注:返回每一个单个分组的元组
print(ret.groups())     # 获取每一个分组里的值,放到1个元组里,返回1个元组
#结果为 ('123', '321', '234')

#捕获分组和非捕获分组
#分组向后引用

示例2:捕获分组

str = "a1 a2 a1 a2"

#正常的是捕获分组
#捕获分组 (分组并捕获,分组之后匹配到的数据,会放到内存中,并且给定一个从1开始的索引)
print(re.search(r"([a-z]\d ){3}([a-z]\d)", str))
#结果为 <re.Match object; span=(0, 11), match='a1 a2 a1 a2'>
print(re.search(r"([a-z]\d)\s+([a-z]\d)\s+\1\s+\2", str))       #\1跟前面分组1一摸一样 \2跟第2个分组一模一样
#结果为 <re.Match object; span=(0, 11), match='a1 a2 a1 a2'>
#分组向后引用 \1 返回的是a1[第1个分组] \2 返回的是a2[第2个分组]

#findall 有捕获分组的话,只会输出捕获分组里的内容
print(re.findall(r"([a-z]\d)\s+([a-z]\d)\s+\1\s+\2", str))
#结果为 [('a1', 'a2')]
#findall只会打印捕获分组里面的东西(a1 a2)

示例3:非捕获分组(?😃

#非捕获分组(?:)  只是分组,不捕获,不会在内存中缓存分组匹配的值,不会分配从1开始的下标索引
str2 = "a1 a2 a2 a1"
ret = re.search(r"(?:\w\d)\s+(\w\d)\s+\1", str2)    # 注:非捕获分组仅仅只是给它分组 不捕获
print(ret)
#结果为<re.Match object; span=(0, 8), match='a1 a2 a2'>
#(?:\w\d)非捕获分组 不会占用下标索引

#findall
#有捕获分组的话,只会输出捕获分组里的内容
#没有捕获分组的话,输出全部内容
ret = re.findall(r"(?:\w\d)\s+(\w\d)\s+\1", str2)   # 注:有捕获分组时 只会输出捕获分组里的内容
print(ret)
#结果为 ['a2']
ret = re.findall(r"(?:\w\d)\s+(?:\w\d)\s+", str2)   # 注:没有捕获分组的话,输出全部内容
print(ret)
#结果为 ['a1 a2 ']

示例4:命名分组

#命名分组       # 注:命名分组合也是捕获分组 取了个名字
ret = re.search(r'(?P<name>\d{3})-\d{3}-(?P<last>\d{3})', "123-321-234abc")
print(ret.group(1))
#结果为 123
print(ret.group("name"))
#结果为 123 命令分组
print(ret.group(2))
print(ret.group("last"))
#结果都为 234 命名分组
print(ret.groupdict())  # 注:匹配到的值变为字典输出
#结果为 {'name': '123', 'last': '234'}     #name就是key,取到的值是value
#获取所有匹配的字符串-字典形式
print(ret.groups())     # 注:获取所有匹配的字符串
#结果为 ('123', '234')

示例5:引用分组

#引用分组
msg = """
<div>hello</div>
<h1>hello</h1>
"""
ret = re.findall(r'(<(\w+)>hello</\2>)', msg)   # 注:外面的分组是第1个 ; 里面的分组是第2个
print(ret)                      # 注:所以后面是 \2
#结果为 [('<div>hello</div>', 'div'), ('<h1>hello</h1>', 'h1')]
#注:一个分组 findall匹配的是一个普通元素,一个以上的分组 findall匹配结果是 元组

ret = re.findall(r'<(\w+)>hello</\1>', msg)	# 注:这种与期望不符
print(ret)
#结果为 ['div', 'h1']

练习4

1、匹配里面的每一个单词,引号部分作为一个单词输出

msg = ‘san chuang tong le, huan ying ni “hello world”, learn python’

示例

import re
msg = 'san chuang tong le, huan ying ni "hello world", learn python'
ret = re.findall(r'\w+|"[\w ]+"', msg)     # 注:\w+ 匹配1次到多次 "[\w ]+" 匹配1次到多次
print(ret)					# 注:\w+ 匹配每一个单词
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', '"hello world"', 'learn', 'python']
#注:匹配到“就会判断是否满足第2个条件
#注:"[\w ]+"  引号里面匹配单词字符 或 空格 匹配1次到多次  "hello world"
#或者
ret = re.findall(r'"[\w ]+"', msg)
ret = re.findall(r'".*"', msg)
print(ret)
#结果为 ['"hello world"']
import re				# 注:没解决问题
msg = 'san chuang tong le, huan ying ni "hello world", learn python'
ret = re.findall(r'\w+|(?<=")(?:[\w ]+)(?=")', msg)     # 注:零宽断言
print(ret)					# 注:没解决问题
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello', 'world', 'learn', 'python']

ret = re.findall(r'(?<=\")(?:[\w ]+)(?=")|\w+', msg)
print(ret)					# 注:解决问题了  因为断言先行
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello world', 'learn', 'python']

2、msg = ‘123@qq.comaaa@126.combbb@163.comcc@abc.com’

#–> 123@qq.com aaa#126.com bbb@163.com

示例

import re
msg2 = 'yyy@xx.com123@qq.comaaa@126.combbb@163.comcc@abc.com'
# --> 123@qq.com  aaa#126.com  bbb@163.com
ret = re.findall("\w+@(qq|163|126).com", msg2)        # 注:捕获分组
print(ret)      # 注:只会捕获到分组的
#结果为 ['qq', '126', '163']
ret = re.findall("\w+@(?:qq|163|126).com", msg2)      # 注:非捕获分组
print(ret)
#结果为 ['com123@qq.com', 'aaa@126.com', 'bbb@163.com']
ret = re.findall("(?:\.com)?(\w+@(?:qq|163|126)\.com)", msg2)
print(ret)  # 注:从左往右依次匹配 com匹配0-1次 满足 ;匹配到com ;后面匹配0次 满足条件
#结果为 ['123@qq.com', 'aaa@126.com', 'bbb@163.com']
#先在最开始找匹配0次或1次;模板往例子里套 @xx没有被匹配到
#findall有捕获分组的情况下 只会输出捕获分组 不会输出非捕获分组 所以没有输出最前面的.com
#注:非捕获分组,不会给它索引下标

ret = re.findall("(\.com)?(\w+@(?:qq|163|126)\.com)", msg2) # 注:捕获分组 作为元组输出
print(ret)          # 注:捕获分组 作为元组输出
#结果为 [('.com', '123@qq.com'), ('', 'aaa@126.com'), ('', 'bbb@163.com')]

3、输出成对存在的中间的内容(test2、test3)

#test1

test2
test3
#–> 输出test2 test3

示例

import re
msg3 = '<html>test1<div>test2</div><a>test3</a></html>'
# reg3 = re.findall(r"(?:<\w+>)\w+(?:</\w+>)",msg3)
ret = re.findall(r'<(\w+)>(\w+)</\1>', msg3)    # 注:\1分组向后引用,表示第1个分组里面的内容
print(ret)      # 注:匹配一组对应的标签
#结果为 [('div', 'test2'), ('a', 'test3')]
#捕获分组,捕获到的项会先放在内存中,并且给它一个索引从1开始

知识点5 正则标记-第三个参数

正则标记-第三个参数
第三个参数
正则标记-第三个参数

示例

#正则标记
import re
msg = """
Python
python
"""
ret = re.findall(r"^python$", 'PYTHOn')
print(ret)  # 注:匹配不上
#结果为 []

#对大小写不敏感的标志位
ret = re.findall(r"^python$", 'PYTHOn',re.I)
print(ret)
#结果为 ['PYTHOn']

ret = re.findall(r"^python$", msg,re.I)
print(ret)  # 注:把msg作为字符串去匹配 ;做一个整体匹配 ; p开头n结尾
#结果为 []
#多行匹配和大小写不明感
ret = re.findall(r"^python$", msg,re.I|re.M)    # 注:re.M 多行匹配
print(ret)  # 注:re.M 进入 多行匹配 模式 每一行都匹配
#结果为 ['Python', 'python']       # 注:|或运算符 支持多条匹配

#re.S                           # 注:使.匹配包括换行在内的所有字符
ret = re.findall(r".+",msg)     # 注:.任意字符匹配 \n换行符 不匹配
print(ret)
#结果为 ['Python', 'python']
#re.S
ret = re.findall(r".+",msg, re.S)   # 注:使.匹配包括换行在内的所有字符
print(ret)				# 注:re.S从头到为全部匹配
#结果为 ['\nPython\npython\n']

知识点6 基本正则匹配-内联标记

基本正则匹配-内联标记
内联标记
基本正则匹配-内联标记
内联标记:(?imx)re
内联标记:(?imx: re)

#注:写在正则表达式前面
(?i:不区分大小写)

i 不区分大小写 # 注:不清楚
m 多行匹配 # 注:不清楚

示例

#内联标记: (?imx)re
import re
ret = re.findall('(?i)^python$', 'Python')
print(ret)
#结果为 ['Python']
ret = re.findall('(?i)^python$', 'Python\npython')
print(ret)
#结果为 []
ret = re.findall('(?im)^python$', 'Python\npython')
print(ret)
#结果为 ['Python', 'python']

#内联标记:(?imx:re)
import re
msg = "Hello Python"
ret = re.findall('(?i:hello) python', "Hello Python")
print(ret)
#结果为 []
ret = re.findall('(?i:hello) Python', "Hello Python")
print(ret)
#结果为 ['Hello Python']

练习7 提取url域名

#提取url域名
#https://music.163.com/#/discover/toplist
#http://www.baidu.com?a=1
#http://news.xinlang.cn
#http://news.xin.lang.cn
#htp://www.baidu.com    # 不属于url

示例

import re
msg = """
https://music.163.com/#/discover/toplist
http://www.baidu.com?a=1
http://news.xinlang.cn
http://news.xin.lang.cn
htp://www.baidu.com
"""
ret = re.findall('(?:https?://)((?:\w+\.)+\w+)', msg,re.M)
print(ret)
#结果为 ['music.163.com', 'www.baidu.com', 'news.xinlang.cn', 'news.xin.lang.cn']
#注:(?:https?://) ?对s匹配0次或1次
#注:(?:\w+\.)+  music.163. 匹配1次以上
#注:\w+         com        匹配1次以上
#注:((?:\w+\.)+\w+) 外面这一层是捕获分组

知识点8 正则表达式断言

正则表达式断言
正则表达式的断言分为:先行断言(lookahead)和后行断言(lookbehind)
正则表达式的先行断言和后行断言一共有4种形式:

·(?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)
·(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)
·(?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)
·(?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)

零宽
· ^python

正向、负向
· 正向:匹配(?=pattern)/(?<=pattern)
· 负向:不匹配(?!pattern)/(?<!pattern)

先行、后行
· 先行:向后匹配(?=pattern)/(?!pattern)
· 后行:向前匹配(?<=pattern)/(?<!pattern)

零宽正向先行断言:(?=pattern)
· 代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern。
· 匹配字符串re,后面能接gular(但不匹配宽度)

零宽负向先行断言:(?!pattern)
· 代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配pattern。
· 匹配字符串re,但是后面不能接gular

零宽正向后行断言:(?<=pattern)
· 代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配pattern。
· 匹配gular,但前面必须是re

零宽负向后行断言 :(?<!pattern)
· 代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配pattern。
· 匹配gular,但前面不能是re

示例

#零宽断言
#匹配位置的参数不会输出
s = "a regular rbgular expression"
#零宽正向先行断言
print(re.findall(r"re(?=gular)",s))     # 注:匹配右边等于gular的re
#结果为 ['re']
#零宽断言 只匹配re gular(位置) 不占宽度gular
s = "a regularression"
# print(re.findall(r"re(?=gular)re(?=ssion)",s))    # 匹配不了2个,所以不要这么用
#结果为[]

#零宽负向先行断言
s = "a regular rbgular expression"
print(re.findall(r"re(?!gular)",s))     # 注:匹配re;后面不等于gular的re
#结果为 ['re']

s = "a regular rbgular expression"
print(re.findall(r"\w+(?=gular)",s))
#结果为 ['re', 'rb']
print(re.findall(r"\w+(?!gular)",s))    # 注:不是很理解
#结果为 ['a', 'regular', 'rbgular', 'expression']

#零宽正向后行断言
s = "a regular rbgular expression"
print(re.findall(r"(?<=re)gular",s))    # 注:匹配左边是re的gular
#结果为 ['gular']

#零宽负向后行断言
s = "a regular rbgular expression"
print(re.findall(r"(?<!re)gular",s))    # 注:匹配左边不是re的gular
#结果为 ['gular']

练习9 使用零宽断言提取ip地址

print(re.findall(r"(?<=inet ).*(?=/)"),ip)
#注:前面用零宽正向先行断言,后面用零宽负向先行断言
#注:前面加<号,后面不加<号
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值