python 模块

#模块


模块的分类

1. 安装包中自带的内置模块
2. 需要下载的第三方模块
3. 自定义模块

内存中,如果这个模块已经加载过了,就不会重复加载.
系统内置名称空间(内置的模块)
sys.path指定的路径 

 

 

__name__属性

__name__是Python内置的一个属性,Python中的函数,模块,类都有这个属性.

1. 模块直接以脚本方式执行的话, __name__ 属性值是固定的字符串: __main__ .
2. 如果模块是被其他模块导入的话,被导入模块的 __name__ 属性就是这个模块的真实名字.

通过__name__属性的值判断是否执行此测试函数:
if __name__ == '__main__':
main()

 

解决名称冲突的方案有三种

  1. 改用 import ... 这种方式导入,后果是使用成员时都必须带上前缀.

  2. 在程序中命名不要和模块中的成员同名.

  3. 使用别名

别名(alias)的使用

import test_module as tm # 相当于定义一个tm变量,指向了被导入的模块对象
print(tm.a) # 使用模块的别名访问变量
tm.test() # 使用模块的别名调用方法
1 2 3

 

限制模块中被导入的成员

 

__all__属性中对成员的限制

在使用 from ... import * 这种方式导入一个模块时,默认情况下这个模块中的所有成员都会被导入.可以在被导入
的模块中使用 __all__ 这个属性控制某些成员可以不被其他模块导入.
# 在my_module.py中添加 __all__ 属性,它是一个由允许被导入的成员名组成的列表.
__all__ = ['f1','f2']
def f1():
print('f1')
def f2():
print('f2')
1 2 3 4 5 6 7

 

 

相对导入

相对导入指的是在同一个路径(包)中的各个模块之间的相互导入时使用的一种方式. 和普通的导入方式不同的是,相对导入只有一种方式:

from 相对路径 import xxx
其中,常用的相对路径就是.和..

 

random模块(随机数)

random模块主要用于获取一定范围的随机数.
常用的方法有:
randint(a,b) :返回一个[a,b]范围内的整数值.注意是闭区间!
random() :返回一个[0.0, 1.0]范围内的浮点数.
uniform(a,b) :返回一个[a,b]或[a,b]范围内的浮点数.
shuffle(x [, random]) :返回一个被打乱顺序的shuttle对象.要求第一个参数必须是可变的数据类型,顺序
打乱之后直接反应在第一个参数表示的对象上.第二个参数表示的是打乱的规则.默认使用的是random.random
函数.如果想对一个不可变数据类型中的元素进行打乱.可以使用sample函数.
sample(x,k) :从x中随机选择k个元素,返回一个列表.如果对一个不可变数据类型中的元素打乱顺序,只需要将
所有的元素随机抽取出来即可.
slice = random.sample(list, 5)  # 从list中随机获取5个元素,作为一个片断返回

 

 

 

time模块 (时间)

time模块表示的是和时间有关的操作.
常用的方法有:
time() :返回从时间原点(1970-01-01 00:00:00)到现在经过的秒数,即:当前的时间戳(timestamp).
gmtime([seconds]) :返回一个以元组形式的结构化时间对象(struct_time),参数是表示从时间原点开始经
过的秒数.默认使用当前的时间戳,即: time() 的返回值.
localtime([seconds]) :和gtime作用相似,只是结果中的某些字段转换成了本地格式.
mktime(t) :和localtime是相反的操作.参数是一个格式化时间对象,返回值表示的是这个时间对象相对时间
原点的秒数.

 

 

time模块中的三大对象

时间戳 time()

结构化 gmtime()

字符串 localtime()

 

时间戳,结构化时间对象,字符串是time模块中非常重要的三大对象.
其中:时间戳和结构化时间对象利于在不同的时区之间进行传播(即:国际化),但是不利于阅读.
字符串便于阅读.但是不利于国际化.
结构化时间对象看起来像一个元组,一共有九个属性字段,可以单独使用其中的属性值.
例如:


import time
t = time.strftime('%Y-%m-%d %H:%M:%S') # 把当前时间转换成指定格式的字符串
print(t)

 

datetime模块

此模块提供了一些有用的类,用来操作时间日期和对象. 主要功能在于对属性值的抽取和计算上.

 

datetime模块中的类

  • date :日期,包含year,month,day三个属性.

  • time :时间,包含hour,minute,second,microsecond,tzinfo属性.

  • datetime :前两者的混合体.

  • timedelta :(时间增量),主要用来在某些属性上进行数学运算.

举例

import datetime
d = datetime.date(2010,10,10)
print(d.year) # 2010
print(d.month) # 10
print(d.day) # 10
t = datetime.time(10,22,15)
print(t.hour) # 10
print(t.minute) # 22
print(t.second) # 15
dt = datetime.datetime(2010,10,10,8,9,20)
print(dt.year,dt.month,dt.day,dt.hour,dt.minute,dt.second) # 2010 10 10 8 9 20
1 2 3 4 5 6 7 8 9
10

 

 

os:和操作系统相关

os.getenv

# 本地写入环境配置 (读取环境变量)
# 变量名 = os.getenv('变量名','默认值')
from dotenv import load_dotenv
load_dotenv("/Users/hunter/work/env_list/local_wechat.env")  # 环境地址

# 获取环境变量
vim local_wechat.env
# 这里的变量名需要和os.getenv(变量名)相同才会引入
# 变量名 = 配置信息
HOSt = 127.0.0.1

 

  • os.remove(file_path) :删除文件

  • os.rmdir(dir_path) :删除空文件夹

  • 删除非空文件夹使用另一个模块:shutil

  • shutil.rmtree(path)

  • os.removedirs(name) :递归删除空文件夹

  • os.rename(src, dst) :文件,目录重命名,目标不能事先存在.

 

举例

import os

os.remove('a.txt')

os.rmdir('aa') # 只能删除空目录

os.removedirs('bb')

os.rename('abc','def')

import os
os.remove('a.txt')
os.rmdir('aa') # 只能删除空目录
os.removedirs('bb')
os.rename('abc','def')

 

shutil删除非空目录.

使用shutil模块删除非空目录.

 

import shutil
shutil.rmtree('aa') # 可以删除带内容目录

 

os.path

在此模块实现一些在路径上的方法

获取功能

 

os.path.abspath(path):返回一个路径的绝对路径.

os.path.abspath(path) :返回一个路径的绝对路径.
如果参数路径是相对的路径,就把当前路径和参数路径的组合字符串当成结果返回.
如果参数路径已经是绝对路径,就直接把参数返回.
如果参数路径以/开始,则把当前盘符和参数路径连接起来组成字符串返回.
import os
print(os.path.abspath('aa')) 
# D:\PycharmProjects\test03\test01\aa
print(os.path.abspath('D:/test/aa')) 
# D:\test\aa
print(os.path.abspath('/bb')) 
# D:\bb



os.path.split(path):分割

返回一个元组,第二个元素表示的是最后一部分的内容,第一个元素表示的是剩余的内容

os.path.split(path) :返回一个元组,第二个元素表示的是最后一部分的内容,第一个元素表示的是剩余的内
容.
如果只是一个盘符或者是以路径分隔符结尾的字符串,则第二个元素为空.
否则第二个元素就是最后一部分的内容.
如果path中不包含路径分隔符,则第一个元素为空.
import os
print(os.path.split('D:/')) # ('D:/', '')
print(os.path.split('.')) # ('', '.')
print(os.path.split('/aa')) # ('/', 'aa')

 

os.path.basename(path):返回path指定的路径的最后一个内容

os.path.basename(path) :返回path指定的路径的最后一个内容.
如果只是一个盘符,或者是以路径分隔符结尾的字符串,则返回空;
否则返回的是路径中的最后一部分内容.
import os
print(os.path.basename('.')) # .
print(os.path.basename('/aa')) # aa
print(os.path.basename('/aa/')) #
print(os.path.basename('D:/test')) # test

 

os.path.dirname(path) :返回一个路径中的父目录部分.

os.path.dirname(path) :返回一个路径中的父目录部分.
如果只是一个盘符,或者是以路径分隔符结尾的字符串,则整体返回.
否则返回的是路径中的父目录部分.
import os
print(os.path.dirname('.')) #
print(os.path.dirname('/aa/')) # /aa
print(os.path.dirname('D:/test')) # D:/
print(os.path.dirname('D:/')) # D:/

 

os.path.getsize(path) :获取文件的字节数.

如果是文件夹,返回0或者是一个不准确的值

print(os.path.getsize('aa')) # 0
print(os.path.getsize('.')) # 4096
print(os.path.getsize('aa/test.txt')) # 6
1 2 3

 

os.path.join(path,*paths) :连接路径

若干个路径为一个路径.

如果路径中有绝对路径,则在这个路径之前的路径都会被丢弃,而从这个路径开始往后拼接.
Windows中盘符一定要带\,否则不认为是一个盘符.
res = os.path.join('aa','bb','cc')
print(res) # aa\bb\cc
res2 = os.path.join('D:/','test')
print(res2) # D:/test

 

os判断功能

os.path.exists(path) :判断路径是否真正存在.
os.path.isabs(path) :判断是否是绝对路径
os.path.isfile(path) :判断是否是文件
os.path.isdir(path) :判断是否是目录

 

sys:和解释器相关

sys.argv :

当以脚本方式执行程序时,从命令行获取参数.
提供了解释器使用和维护的变量和函数.
sys.argv :当以脚本方式执行程序时,从命令行获取参数.
argv[0]表示的是当前正在执行的脚本名.argv[1]表示第一个参数,以此类推.
import sys
print('脚本名称:',sys.argv[0])
print('第一个参数是:',sys.argv[1])
print('第二个参数是:',sys.argv[2])

 

使用cmd命令行方式运行该脚本: python test.py hello world

 

sys.modules 返回系统已经加载的模块,以字典形式返回.

sys.modules :返回系统已经加载的模块,以字典形式返回.
对这个字典中的值进行修改并没有什么具体意义.反而有时会引发异常.
常用来作为是否重新加载一个模块的判断依据.

 

sys.path:系统寻找模块的路径

sys.path :系统寻找模块的路径.可以通过PYTHONPATH来进行初始化.
由于是在程序执行的时候进行初始化的,所以,路径的第一项path[0]始终是调用解释器的脚本所在的路径.如果
是动态调用的脚本,或者是从标准输入读取到脚本命令,则path[0]是一个空字符串.程序中可以随时对这个路径
进行修改.以达到动态添加模块路径的目的.

 

json和pickle序列化

json:

操作JSON(一种数据交换格式)相关

  1. 不同语言都遵循的一种数据转化格式,即不同语言都使用的特殊字符串。(比如Python的一个列表[1, 2, 3]利用json转化成特殊的字符串,然后在编码成bytes发送给php的开发者,php的开发者就可以解码成特殊的字符串,然后在反解成原数组(列表): [1, 2, 3])

  2. json序列化只支持部分Python数据结构:dict,list, tuple,str,int, float,True,False,None

 

l1 = [i for i in range(10000)]
# l1 --->bytes
# b1 = l1.encode('utf-8')  # 不能直接转换
# l1转化成字符串在转化成bytes
s1 = str(l1)
b1 = s1.encode('utf-8')
# print(b1)

# 岑哥接收了b1
s2 = b1.decode('utf-8')
# print(s2,type(s2))

# str 我们学过的str

# dic = {'username': '太白', 'password': 123,'status': True}
import json
#dumps loads 主要用于网络传输,但是也可以读写文件
# 特殊的字符串
# st = json.dumps(dic,ensure_ascii=False)
# print(st,type(st))
# # 反转回去
# dic1 = json.loads(st)
# print(dic1,type(dic1))

# 写入文件
# l1 = [1, 2, 3, {'name': 'alex'}]
# 转化成特殊的字符串写入文件
# with open('json文件',encoding='utf-8',mode='w') as f1:
#     st = json.dumps(l1)
#     f1.write(st)

# 读取出来还原回去
# with open('json文件',encoding='utf-8') as f2:
#     st = f2.read()
#     l1 = json.loads(st)
#     print(l1,type(l1))
# 特殊的参数
l1 = [1, 2, 3, {'name': 'alex'}]

# dump load 只能写入文件,只能写入一个数据结构
# with open('json文件1',encoding='utf-8',mode='w') as f1:
#     json.dump(l1,f1)

# 读取数据
# with open('json文件1',encoding='utf-8') as f2:
#     l1 = json.load(f2)
#     print(l1,type(l1))


# 一次写入文件多个数据怎么做?

# 错误示例:
# dic1 = {'username': 'alex'}
# dic2 = {'username': '太白'}
# dic3 = {'username': '大壮'}
# with open('json文件1',encoding='utf-8',mode='w') as f1:
#     json.dump(dic1,f1)
#     json.dump(dic2,f1)
#     json.dump(dic3,f1)


# 读取数据
# with open('json文件1',encoding='utf-8') as f1:
#     print(json.load(f1))
    # print(json.load(f1))
    # print(json.load(f1))


# 正确写法:
dic1 = {'username': 'alex'}
dic2 = {'username': '太白'}
dic3 = {'username': '大壮'}
# with open('json文件1',encoding='utf-8',mode='w') as f1:
#     f1.write(json.dumps(dic1) + '\n')
#     f1.write(json.dumps(dic2) + '\n')
#     f1.write(json.dumps(dic3) + '\n')

# with open('json文件1',encoding='utf-8') as f1:
#     for i in f1:
#         print(json.loads(i))

 

pickle模块:

  1. 只能是Python语言遵循的一种数据转化格式,只能在python语言中使用。

  2. 支持Python所有的数据类型包括实例化对象。

l1 = [1, 2, 3, {'name': 'alex'}]

# dumps loads 只能用于网络传输
# import pickle
# st = pickle.dumps(l1)
# print(st)  # bytes
#
# l2 = pickle.loads(st)
# print(l2,type(l2))

# dump load 直接写入文件
# import pickle
# dic1 = {'name':'oldboy1'}
# dic2 = {'name':'oldboy2'}
# dic3 = {'name':'oldboy3'}
#
# f = open('pick多数据',mode='wb')
# pickle.dump(dic1,f)
# pickle.dump(dic2,f)
# pickle.dump(dic3,f)
# f.close()
# import pickle
# f = open('pick多数据',mode='rb')
# print(pickle.load(f))
# print(pickle.load(f))
# print(pickle.load(f))
# f.close()

import pickle
def func():
    print('in func')

# f = open('pick对象',mode='wb')
# pickle.dump(func,f)
# f.close()

# f = open('pick对象', mode='rb')
# ret = pickle.load(f)
# print(ret)
# ret()
import pickle
with open("account", mode="rb") as f:
    while 1:
        try:
            res = pickle.load(f)
            l1.append(res)
        except:
            break
读的时候要try,因为不会自动停止超过内容就会报错

 

总结

json

  1. 序列化的结果是字符串

  2. 只支持部分数据类型

  3. 可以跨编程语言传输数据

  4. 不能多次读写序列化文件

pickle

  1. 序列化的结果是字节

  2. 支持python所有的数据类型

  3. 只在python中使用

  4. 可以多次读取序列化文件

json更加通用,pickle更有针对性

dump 文件传输 dumps 网络传输

load 文件传输 loads 网络传输

 

hashlib加盐

# 加盐

# s2 = '19890425'
# ret = hashlib.md5('太白金星'.encode('utf-8'))
# ret.update(s2.encode('utf-8'))
# print(ret.hexdigest())  # 84c31bbb6f6f494fb12beeb7de4777e1


# 动态的盐
# s2 = '19890425'
# ret = hashlib.md5('太白金星'[::2].encode('utf-8'))
# ret.update(s2.encode('utf-8'))
# print(ret.hexdigest())  # 84c31bbb6f6f494fb12beeb7de4777e1

 

登陆加密

把用户名和密码信息加密后,通过序列化的方式存储到本地文件中. 并通过控制台输入信息进行验证.

 

import hashlib
import json
# 对用户名和密码进行加密
def get_md5(username,password):
encrypt = hashlib.md5(username.encode('utf-8'))
encrypt.update(password.encode('utf-8'))
return encrypt.hexdigest()
username = 'Andy'
password = '123'
# 将用户信息保存到文件中:
# 格式:用户名|用户名和密码加密后的字符串
with open('login.info',mode='wt',encoding='utf-8') as f:
json.dump(username + '|' + get_md5(username,password),f)
# 验证
name = input('input username:')
passwd = input('input password:')
# 反序列化出info
with open('login.info',mode='rt',encoding='utf-8') as f:
info = json.load(f)
username,password = info.split('|')
if name == username and get_md5(name,passwd) == password:
print('登录成功')
else:
print('登录失败')

 

requests查看网络源码

import requests
response  =requests.get("https://www.baidu.com")
ret.text

 

 

re模块

正则表达式的关系

 

有了re模块就可以在python语言中操作正则表达式了

正则表达式 *

re模块 -- regex 正则表达式

 

正则表达式定义

  一套规则 - 匹配规则

 

正则规则

[abc] 一个中括号只表示一个字符位置

匹配a或者b或者c

[0-9] 根据ascii进行范围的比对

[a-z]

[A-Z]

[a-zA-Z] 大小写

[0-9a-z]

[0-9a-zA-Z_]

在正则表达式中能够帮助我们表示匹配的内容的符号都是正则中的 元字符

元字符 -- 匹配内容的规则
# []  [^]
# \d 匹配数字
# \w 匹配字母或数字或下划线
# \s 匹配任意的空白符
# \t 匹配一个制表符
# \n 匹配一个换行符
# \b 匹配一个单词的结尾
# \W  非数字字母下划线
# \D  非数字
# \S  非空白
# [\d]  \d
# [\d\D] [\w\W] [\s\S]  表示匹配所有
# .   匹配除了换行符之外的所有
# [^\d]  匹配所有的非数字
# [^1]  匹配所有的非数字
# ^     匹配一个字符串的开始
# $     匹配一个字符串的结尾
# a表达式|b表达式     匹配a或者b表达式中的内容,如果匹配a成功了,不会继续和b匹配
#                       所以,如果两个规则有重叠部分,总是把长的放在前面
# ()    匹配括号内的表达式,也表示一个组

 

记忆元字符 : 都是表示能匹配哪些内容,一个元字符总是表示一个字符位置上的内容
    \d \w \s \t \n \D \W \S
    [] [^] .
    ^ $
    | ()

 

# 量词
    # {n}  表示匹配n次
    # {n,} 表示匹配至少n次
    # {n,m}表示至少匹配n次,至多m次
    # ? 表示匹配0次或1次 {0,1}
    # + 表示1次或多次    {1,}
    # * 表示0次或多次    {0,}

# 匹配0次
    # 整数 \d+
    # 小数 \d+\.\d+
    # 整数或小数 : \d+\.?\d*

    # 分组的作用 : \d+(\.\d+)?

 

# 判断用户输入的内容是否合法,如果用户输入的对就能查到结果,如果输入的不对就不能查到结果
    # ^1[3-9]\d{9}$
# 从一个大文件中找到所有符合规则的内容
    # 1[3-9]\d{9}

 

 

贪婪匹配

在量词范围允许的情况下,尽量多的匹配内容 ​ .*x 表示匹配任意字符 任意多次数 遇到最后一个x才停下来

非贪婪(惰性)匹配

.*?x 表示匹配任意字符 任意多次数 但是一旦遇到x就停下来

    总是在量词范围内尽量多匹配 - 贪婪
​    总是在量词范围内尽量少匹配 - 惰性
​    .*?x  匹配任意内容任意次数 遇到x就停止
​    .+?x  匹配任意内容至少1次 遇到x就停止

 

转义符

原本有特殊意义的字符,到了表达它本身的意义的时候,需要转义 ​ 有一些有特殊意义的内容,放在字符组中,会取消它的特殊意义 ​ [().*+?] 所有的内容在字符组中会取消它的特殊意义 ​ [a-c] -在字符组中表示范围,如果不希望它表示范围,需要转义,或者放在字符组的最前面\最后面

    . 有特殊的意义,取消特殊的意义\.
​    取消一个元字符的特殊意义有两种方法
​        在这个元字符前面加\
​        对一部分字符生效,把这个元字符放在字符组里
​            [.()+?*]

 

正则表达式网站

http://tool.chinaz.com/regex/?qq-pf-to=pcqq.group

 

练习

练习
# 18/15位的身份证号
    # 15
        # 1-9 15
        # [1-9]\d{14}
    # 18
        # 1-9 16 0-9/x
        # [1-9]\d{16}[\dx]
        # [1-9]\d{16}[0-9x]
#[1-9]\d{16}[0-9x]|[1-9]\d{14}
# ^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
# [1-9]\d{14}(\d{2}[\dx])?
# ^[1-9]\d{14}(\d{2}[\dx])?$
View Code

 

 

findall会优先显示分组内的内容

会优先显示分组内的内容

取消优先显示(?:正则)

ret = re.findall('<\w+>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
print(ret)
结果
['askh930s02391j192agsj']

 

search返回第一个符合条件

  只能返回第一个符合条件的项

  得到的结果需要.group取值

  默认获取完整的匹配结果

  通过group(n)取第n个分组中的内容

ret = re.search('<(\w+)>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
print(ret.group())
print(ret.group(1))
print(ret.group(2))
结果
<h1>askh930s02391j192agsj</h1>
h1
askh930s02391j192agsj

 

为什么要用分组,以及findall的分组优先到底有什么好处

# 为什么要用分组,以及findall的分组优先到底有什么好处
exp = '2-3*(5+6)'
# a+b 或者是a-b 并且计算他们的结果
ret = re.search('\d+[+]\d+',exp)
print(ret)
a,b = ret.group().split('+')
print(int(a)+int(b))
1.re模块结尾
2.带参数的装饰器\递归函数

如果我们要查找的内容在一个复杂的环境中
我们要查的内容并没有一个突出的 与众不同的特点 甚至会和不需要的杂乱的数据混合在一起
这个时候我们就需要把所有的数据都统计出来,然后对这个数据进行筛选,把我们真正需要的数据对应的正则表达式用()圈起来
这样我们就可以筛选出真正需要的数据了

 

split切割

ret = re.split('\d+','alex222wusir')
结果
# ['alex', 'wusir']
ret = re.split('\d(\d)\d','alex123wusir')
结果
# ['alex', '2', 'wusir']
print(ret)

 

sub替换

ret = re.sub('\d+','H','alex123wusir456',1)
print(ret)
结果
# alexHwusir456
# 替换掉遇到的第一个

 

 

subn全部替换

ret = re.subn('\d+','H','alex123wusir456')
print(ret)
结果
('alexHwusirH', 2)

 

match默认从头开始匹配

ret = re.match('\d+','123eva456taibai')
print(ret.group())
结果
#123
match  用户输入的内容匹配的时候,要求用户输入11位手机号码,^手机号正则$
match('手机号正则$','123eva456taibai')  规定这个字符号必须是什么样的
search('^手机号正则$','123eva456taibai') 用来寻找这个字符串中是不是含有满足条件的子内容
ret1 = re.search('^\d+','123eva456taibai')
print(ret1.group())
结果
#123

 

 

compile节省代码时间的工具

假如同一个正则表达式要被使用多次
节省了多次解析同一个正则表达式的时间
ret = re.compile('\d+')
res1 = ret.search('alex37176')
res2 = ret.findall('alex37176')
print(res1.group())
print(res2)
结果
37176
['37176']
findall返回的是列表

 

 

finditer节省空间

ret = re.finditer('\d+','agks1ak018093')
for i in ret:
    print(i.group())
结果
# 1
# 018093

 

(?p:<组名>正则) ?p=组名 ?:取消优先

 节省内存,空间

  1. 分组命名:(?P<名字>正则表达式)

  2. (?P<组名>正则) (?P=组名)

 

re模块总结

re模块的常用方法
findall(正则,待匹配字符串,flag) :  返回所有匹配项的列表
search : 返回一个变量,通过group取到的是第一个匹配的项
finditer :返回一个迭代器,通过迭代取到的是一个变量,通过group取值
match : 从头开始找第一个,其他和search一样

compile(正则):同一个正则表达式需要多次使用的时候提前编译来节省时间

split 通过正则表达式匹配的内容进行分割
sub 替换,通过正则表达式匹配的内容来进行替换
subn 替换,在sub的基础上,返回一个元组,第一个内容是替换结果,第二个是替换次数

 

例题

# 标签匹配
# <h1>aksfgi031oq3h</h1><h2>sdhyqo-120v b,</h2>
# re.findall('<\w+>(.*?)</\w+>',exp)
# ret = re.search(r'<(\w+)>(.*?)</\1>',exp)
# ret.group(2)

 

# 用户输入身份证号匹配
# re.match('^[1-9]\d{14}(\d{2}[\dx])?$',ident_num)
# ^([1-9]\d{16}[\dx]|[1-9]\d{14})$

 

# 分组命名 取消分组优先
# (?P<组名>正则)  (?P=组名)  (?:正则)

 

# 2、匹配年月日日期 格式2018.12.16
# [1-9]\d{3}-(1[0-2]|0?[1-9])-([12]\d|3[01]|0?[1-9])
# [1-9]\d{3}-(1[0-2]|0?[1-9])-([12]\d|3[01]|0?[1-9])
# [1-9]\d{3}(?P<sub>[^\d])(1[0-2]|0?[1-9])(?P=sub)([12]\d|3[01]|0?[1-9])

 

posted @ 2019-08-12 20:38  驰念  阅读(432)  评论(0编辑  收藏  举报