python--正则表达式
正则表达式
https://www.cnblogs.com/qflyue/p/8252528.html
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
'''
python 正则 re 用法
字符类:
[ ]匹配括号内多个字符中的任意一个字符
[^ ]表示匹配除了括号内的任意一个字符
- [^0-9]:匹配除了数字的任意一个字符
- [a-z]:匹配任意一个小写字母
- [A-Z]:匹配任意一个大写字母
- [a-zA-Z0-9]:匹配任意一个小写或大写字母或数字
特殊字符类:
- .: 匹配除了\n之外的任意字符; [.\n]
- \d: digit–(数字), 匹配一个数字字符, 等价于[0-9]
- \D: 匹配一个非数字字符, 等价于[^0-9]
- \s: space(广义的空格: 空格, \t, \n, \r), 匹配单个任何的空白字符;
- \S: 匹配除了单个任何的空白字符;
- \w: 字母数字或者下划线, [a-zA-Z0-9_]
- \W: 除了字母数字或者下划线, [^a-zA-Z0-9_]
https://blog.csdn.net/m0_37206112/article/details/87393644
'''
# todo: match 方法
# 从字符串的起始位置开始匹配
# - 如果起始位置没有匹配成功,则返回 None
# - 如果起始位置匹配成功,则返回一个对象,通过 group() 方法来获取匹配的内容
import re
obj = re.match(r'\d', '1wearehappy')
# if obj:
# print(obj.group()) # 1
# else:
# print('没有匹配到')
# todo: search 方法
# 会扫描整个字符串,只返回第一个匹配成功的nei
obj1 = re.search(r'\d', '阅读数为2,点赞数是10')
# print(obj1.group()) # 2
# todo: findall 方法
# 会扫描整个字符串,获取匹配的所有内容,返回list
obj2 = re.findall(r'\d+', '阅读数为2,点赞数是10')
# print(obj2) # ['2', '10']
'''
问题描述:
北美电话的常用格式:(eg: 2703877865)
前3位: 第一位是区号以2~9开头 , 第2位是0~8, 第三位数字可任意;
中间三位数字:第一位是交换机号, 以2~9开头, 后面两位任意
最后四位数字: 数字不做限制;
'''
def is_vaild(pattern, num):
obj3 = re.search(pattern, num)
if obj3:
return ('{}合法'.format(num))
else:
return ('{}不合法'.format(num))
if __name__ == '__main__':
pattern = r'[2-9][0-8][0-9][2-9]\d{6}'
num = '4651151456'
num1 = '2652151455'
is_vaild(pattern, num1) # 4651151456 合法
is_vaild(pattern, num) # 2652151455 不合法
'''
问题描述:
指定字符出现的次数
*: 代表前一个字符出现0次或者无限次; \d*, .*
+: 代表前一个字符出现一次或者无限次; d+
?: 代表前一个字符出现1次或者0次; 假设某些字符可省略, 也可以不省略的时候使用,即去贪婪
{m}: 前一个字符出现m次;
{m,}: 前一个字符至少出现m次; * == {0,}; + ==={1,}
{m,n}: 前一个字符出现m次到n次; ? === {0,1}
'''
import re
# *: 代表前一个字符出现0次或者无限次; \d *,.*
print(re.findall(r'\d*', '234')) # ['234', '']
print(re.findall(r'.*', 'hello223%')) # ['hello223%', '']
print(re.findall(r'd*', 'ddhello223%')) # ['dd', '', '', '', '', '', '', '', '', '', '']
# +: 代表前一个字符出现一次或者无限次; d+
print(re.findall(r'd+', '')) # []
print(re.findall(r'd+', 'dddderrttt')) # ['dddd']
print(re.findall(r'\d+', '阅读数: 8976 点赞数:900')) # ['8976', '900']
# ?: 代表前一个字符出现1次或者0次; 假设某些字符可省略, 也可以不省略的时候使用
# 2019-10
print(re.findall(r'\d+-?\d+', '2019-10')) # ['2019-10']
print(re.findall(r'\d+-?\d+', '201910')) # ['201910']
print(re.findall(r'\d{4}-?\d{1,}', '2019-1')) # ['2019-1']
print(re.findall(r'\d{4}-?\d{1,2}', '2019-10')) # ['2019-10']
print(re.findall(r'\d+-?\d+', '201910')) # ['201910']
print(re.findall(r'(\d+?)-(\d+)', '2019-10')) # [('2019', '10')]
'''
问题描述:
练习: 匹配一个163邮箱;(xdshcdshvfhdvg@qq.com) --- 如果想在正则里面匹配真实的. , \.
xdshcdshvfhdvg(可以由字母数字或者下划线组成, 但是不能以数字或者下划线开头; 位数是6-12之间)
'''
email = 'weldrfgo@163.com'
pattern = r'^[a-zA-Z]\w{5,11}@163.com$'
obj3 = re.search(pattern, email)
# print(obj3.group())
'''
问题描述:
检查某段给定的文本是否是一个符合需要的URL;
思路:
1). 检查URL是否以web浏览器普遍采用的通信协议方案开头: http, https, ftp file
2). 协议后面紧跟 ?/
3). 协议后面字符任意;
'''
def isUrl(url):
pattern = r'^(http|https|ftp|file)://.+$'
obj4 = re.findall(pattern, url)
if obj4:
return True
else:
return False
if __name__ == '__main__':
# print(isUrl('fi4le:///tmp'))
# print(isUrl('http://www.baidu.com'))
# print(isUrl('https://www.baidu.com'))
# print(isUrl('ftp://www.baidu.com'))
pass
'''
问题描述
北美电话号码的合法性
1234567890
123-456-7890
123.456.7890
123 456 7890
(123) 456 7890
统一格式为:
(123) 456-7890
'''
def is_phone(tel):
pattern = r'\(?(?P<firstNum>[2-9][0-8]\d)\)?[-\.\s]?(?P<secondNum>[0-8]\d{2})[-\.\s]?(?P<thirdNum>\d{4})'
obj5 = re.search(pattern, tel)
if obj5:
info = obj5.groupdict()
print(info)
formatPhone = "(%s) %s-%s" % (info['firstNum'],
info['secondNum'], info['thirdNum'])
print(formatPhone)
return True
return False
# print(is_phone('177-777-7777'))
# print(is_phone('(777) 777 7890'))
'''
问题描述:
字符串的替换与分离
'''
import re
s = 'westos is a company'
print(s.replace('westos', 'fentiao')) # fentiao is a company
# 将westos和company都替换位cat
print(re.sub(r'(westos|company)', 'cat', s)) # cat is a cat
# 将所有的数字替换位0;
s1 = "本次转发数位100, 点赞数为80;"
print(re.sub(r'\d+', '0', s1)) # 本次转发数位0, 点赞数为0;
'''替换 sub 使用函数'''
def addNum(Obj):
# num是一个字符串
num = Obj.group()
# newNum是一个整形数
newNum = int(num) + 1
return str(newNum)
# .*?
# 对于所有的数字加1;
print(re.sub(r'\d+', addNum, s1)) # 本次转发数位101, 点赞数为81;
s2 = '1+2=3'
print(re.split(r'[+=]', s2))
'''
问题描述:
匹配URL地址
'''
import re
url = 'http://www.baidu.com'
pattern = r'^((https|http|ftp|rtsp|mms)?:\/\/)\S+'
# 进行分组的时候, findall方法只返回分组里面的内容;
# print(re.findall(pattern, url))
resObj = re.search(pattern, url)
if resObj:
# group方法会返回匹配的所有内容;
print(resObj.group())
# groups方法返回分组里面的内容;
print(resObj.groups())
'''
问题描述
匹配用户名
字符串是否包含中文 []表示匹配方括号的中任意字符,
\u4e00是Unicode中汉字的开始,\u9fa5则是Unicode中汉字的结束
[\w-\u4e00-\u9fa5]+
'''
import re
user = '西部开源123'
pattern = r'[\w\-\u4e00-\u9fa5]+'
print(re.findall(pattern, user))
group 和 groups 的区别
import re
a = "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group() #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')
上面正则表达式中的三组括号把匹配结果分成三组
- group() 同group(0)就是匹配正则表达式整体结果
- group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
- groups()是把所有匹配出来的分组加入元组中
import re
a = "123abc456"
print re.search("[0-9]*[a-z]*[0-9]*",a).group() #123abc456
print re.search("[0-9]*[a-z]*[0-9]*",a).group(0) #123abc456
print re.search("[0-9]*[a-z]*[0-9]*",a).groups() #()
当然正则表达式中没有括号分组,group(1)和groups肯定不对了。