10正则表达式

10-1 初识正则表达式

# 正则表达式
# JSON(XML)

什么是正则表达式?
正则表达式是一个特殊的字符串序列,一个字符串是否与我们所设定的这样的字符序列相匹配。

快速检索文本、实现一些替换文本操作

1.检查一串数字是否是电话号码
2.检测一个字符串是否符合email
3.把一个文本里指定的单词替换为另一个单词。

# Q1:检测下列字符串中是否含有Python?
a = 'c|c++|java|c#|python|iavascript'
print(a.index('python')>-1)#用Python的内置函数index,这是方法一
print('python'in a)#这种方法也可以。打印结果如图1

# 接下来看看如何用正则表达式检测Python是否在字符串a里?

import re #python提供了一个re模块,re模块里提供了好多方法供我们操作正则表达式
a = 'c|c++|java|c#|python|iavascript'
r = re.findall('python',a)#这两个参数第一个是要填入需要匹配的正则表达式,第二个是需要传入所在字符串
print(r)
# 打印结果如图2所示,是一个含有Python字符串的列表,返回的结果是常量字符串,看似毫无意义。正则表达式的
# 灵魂在于  规则 !!!! 这个例子的规则抽象性太弱。很明确的告诉你,在字符串里找Python

# 看看完整的代码
import re 
a = 'c|c++|java|c#|python|iavascript'
r = re.findall('python',a)
if len(r) > 0:
    print('字符串中含有Python')  #打印结果如图3
else:
    print('NO')

image
image
image

10-2 元字符与普通字符

# Q1:如何提取下列字符串中的所有的数字?

a = 'c0c++7java8c#9python6javascript'

# 看下列代码
import re 
a = 'c0c++7java8c#9python6javascript'
r = re.findall('\d',a)   #0~9这些阿拉伯数字的正则表达式抽象就是“\d”
print(r)
# 打印结果如图1

# 总结一下:10-1中的例子‘Python’是一个普通字符,‘\d’是一个元字符,他们既可以单独使用,也可以搭配使用
# 百度正则表达式会出现很多元字符,根据自己的业务需求决定总结要使用哪种元字符!

# Q2:如何提取下列字符串中的所有字母,将数字除掉?

a = 'c0c++7java8c#9python6javascript'

# 看下列代码
import re 
a = 'c0c++7java8c#9python6javascript'
r = re.findall('\D',a)   #  “\D”就是将数字去除
print(r)
# 打印结果如图2

10-3 字符集

# 看看正则表达式的第一个模式:字符集
#    字符集
# Q1:找出字符串所给单词中,中间一个是c或者f的单词!!?
import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[cf]c',s)#字符集使用中括号,把需要抽象的字符集写在中括号里面!!
# 中括号两边的字母起到定界的作用!中括号里面的表示或的关系!!!
print(r)#打印结果如图1

# Q2:找出字符串所给单词中,中间一个不是c不是f不是d的单词!!?
import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[^cdf]c',s)#字符集使用中括号,里面的向上的小箭头表示取反的操作

print(r)#打印结果如图2

# Q3:找出字符串所给单词中,找出中间一个是从c到f的单词!!?
import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[c-f]c',s)#这里如果写成r = re.findall('a[cdef]c',s)这也是正确的,两种表述都对!

print(r)#打印结果如图3

image
image
image

10-4 概括字符集

# 概括字符集
# 目前所学习的两个  \d  \D
# \w 匹配的都是单词字符  \W表示非单词字符,如空格,\n \t \r都是非单词字符,用\W,在打印结果中都可以看到
#   \s用来匹配空白字符如:\n \t \r (&除外不能匹配,&有别于\n \t \r的特殊字符)  \S用来匹配非空白字符
#补充一点:  . 匹配除换行符\n以外其他所有字符
# 看下列代码
import re 
a = 'python1111java678php'
r = re.findall('[0-9]',a)  # 表示的意思是\d,打印的都是数字
print(r)

import re 
a = 'python1111java678php'
r = re.findall('[^0-9]',a)  # 表示的意思是\D,打印的都是字母
print(r)
# 上述打印结果如图1

# Q1:在一个字符串中,想要匹配所有的数字和字母,怎么操作?
import re 
a = 'python1111java678php'
r = re.findall('[\w]',a)  # \w,打印的都是字母和数字
print(r)
# 打印结果如图2

# Q2:在一个字符串中,想要匹配所有的数字和字母,怎么操作?
import re 
a = 'python1111java&678php'#在字符串中加入&,看看结果如何?
r = re.findall('[\w]',a)  # \w,打印的都是字母和数字
print(r)
# 打印结果如图2,跟图2一样

# \w 表示单词字符,意义如下:
import re 
a = 'python1111java&678php'
r = re.findall('[A-Za-z0-9_]',a) # \w 表示就是中括号里面的[A-Za-z0-9_]意思是:大小写a-z,数字0-9,还有下划线
print(r)

# 看看下面的例子
import re 
a = 'python1111java&678php___'
r = re.findall('[A-Za-z0-9_]',a) #相当于 \w
print(r)
# 打印结果如图3 ,看到了下划线

# Q3:在一个字符串中,想要匹配所有的非数字和字母,怎么操作?
import re 
a = 'python1111java&678php'#在字符串中加入&,看看结果如何?
r = re.findall('[\W]',a)  # \W,打印的都是非字母和数字
print(r)
# 打印结果如图4

# Q4:在一个字符串中,想要匹配所有的空白字符,怎么操作?
import re 
a = 'python111\t1java\n&678php\r'
r = re.findall('[\s]',a)  # \s,打印的都是空白字符
print(r)
# 打印结果如图5

image
image
image
image
image

10-5 数量词

10-6 贪婪与非贪婪

#数量词

# Q1:在一个字符串中,想要匹配所有的字母,怎么操作?
import re 
a = 'python1111java678php'
r = re.findall('[a-z]',a)  # a-z打印所有的字母
print(r)
# 打印结果如图1

# Q2:在一个字符串中,想要匹配所有的完整的单词,怎么操作?
import re 
a = 'python1111java678php'
r = re.findall('[a-z]{3}',a)  # [a-z]{3}表示单词以3个一组出现
print(r)
# 打印结果如图2,结果2中都是3个一组,并不是完整的字母,怎么办?

# Q3:在一个字符串中,想要匹配所有的完整的单词,怎么操作?
import re 
a = 'python1111java678php'
r = re.findall('[a-z]{3,6}',a)  # [a-z]{3,6}表示单词出现的形式,最少以3个字母,最多以6个字母出现。字母乘以数量的形式。
print(r)
# 打印结果如图3,是我们想要的结果

# 贪婪与非贪婪
# 在Python中,默认的是贪婪的匹配方式。看个例子
import re 
a = 'python1111java678php'
r = re.findall('[a-z]{3,6}',a) 
print(r)
# 根据图3的打印结果,当匹配到3个字母的时候,输出也是正确的,只不过Python采用的贪婪的匹配方式,会尽量多的往下匹配

# 来看下非贪婪的匹配
import re 
a = 'python1111java678php'
r = re.findall('[a-z]{3,6}?',a) #[a-z]{3,6}?加这个问号就表示非贪婪的匹配
print(r)
# 打印结果如图4,这种非贪婪的匹配方式,跟{3}的匹配方式相同!

image
image
image
image

10-7 匹配0次1次或者无限多次

# 数量词
#   *  匹配*前面的字符0次或者无限多次
# +  匹配*前面的字符1次或者无限多次
# ?  匹配?前面的字符0次或者1次
import re 
a = 'pytho0python1pythonn2'
r = re.findall('python*',a) #  用* ,匹配*前面的字符0次或者无限多次
print(r)
# 打印结果如图1

# +  匹配*前面的字符1次或者无限多次
import re 
a = 'pytho0python1pythonn2'
r = re.findall('python+',a) #  用+ ,匹配+前面的字符1次或者无限多次
print(r)
# 打印结果如图2

# ?  匹配?前面的字符0次或者1次
import re 
a = 'pytho0python1pythonn2'
r = re.findall('python?',a) #  用? ,匹配?前面的字符0次或者1次
print(r)
# 打印结果如图3 ,打印第三个Python的时候,虽然是pythonn,但是打印出来的仍然是Python,
# 只是匹配了0次或者1次,多余的n都会被略去

# 在和贪婪与非贪婪中的?相比较的时候,贪婪与非贪婪出现的是范围,加问号表示非贪婪
# 这里表示:匹配?前面的字符0次或者1次

# 看看下面三段代码的意义和结果
import re 
a = 'pytho0python1pythonn2'
r = re.findall('python?',a) #  用? ,匹配?前面的字符0次或者1次
print(r)

import re 
a = 'pytho0python1pythonn2'
r = re.findall('python{1,2}?',a) #  用python{1,2}?表示非贪婪
print(r)

import re 
a = 'pytho0python1pythonn2'
r = re.findall('python{1,2}',a) #  用python{1,2}表示贪婪
print(r)
# 打印结果如图4,三段代码的结果截然不同,意义不一样

image
image
image
image

10-8 边界匹配符

# 边界匹配
# Q1:怎么判断一个QQ号码在4~8位之间?
import re
a = '100001'

r = re.findall('\d{4,8}',a)#用此种方法可以判断出来
print(r)
# 打印结果如图1

# Q2:怎么判断一个QQ号码在4~8位之间?
import re
a = '101'

r = re.findall('\d{4,8}',a)#用此种方法可以判断出来
print(r)
# 打印结果如图2

# Q3:怎么判断一个QQ号码在4~8位之间?
import re
a = '100000001'

r = re.findall('\d{4,8}',a)#用此种方法可以判断出来
print(r)
# 打印结果如图3


# Q4:如何完全匹配一个QQ号码?要用到边界匹配了,如果一个QQ号码在4-8位之间,下面能匹配吗?
import re
a = '100000001'

r = re.findall('^\d{4,8}$',a)#用^\d{4,8}$前面加上^,表示从开始匹配,后面加上一个$,代表从后面开始匹配。一前一后表示完全匹配这个字符串
print(r)
# 打印结果如图4,结果是空的列表。无法匹配4-8的号码

# 看看下列代码,深入理解边界匹配!
import re
a = '100000001'

r = re.findall('000',a)#用此种方法可以判断出来
print(r)
# 打印结果如图5,两组000


import re
qq = '100000001'

r = re.findall('^000',a)#在000前面加一个向上的^
print(r)
# 打印结果是空列表,因为从开始匹配的数字是1,不是0,所以打印的是空列表

import re
qq = '100000001'

r = re.findall('000$',a)#在000的后面加上一个$
print(r)
# 打印结果是空列表,因为从末尾开始匹配的三个字母必须是000,但是目前的001,所以不匹配!所以打印的是空列表

10-9 组

# 组的概念   一个小括号就代表一个组

# Q1:判断一个字符串里是否包含3个Python?!
import re 
a = 'pythonpythonpythonpythonpython'
r = re.findall('pythonpythonpython',a)#这种方法是可行的
print(r)
# 打印结果如图1

# 看看方法二
import re 
a = 'pythonpythonpythonpythonpython'
r = re.findall('(python){3}',a)#(python),加上(),代表就是一个组,()里的内容是且的关系,【】里的是或的关系
print(r)

image

10-10 匹配模式参数

# 10-10 匹配模式参数

import re
lanuage = 'pythonC#javaphp'
r = re.findall('c#',lanuage)#将小写的c#看看打印出来的是啥?
print(r)
# 打印结果如图1,是一个空列表,因为区分大小写

# 那么有没有一种方法可以忽略大小写呢?看看下面的例子
import re
lanuage = 'pythonC#javaphp'
r = re.findall('c#',lanuage,re.I)#第三个参数就是flags,就是指的就是匹配模式
print(r)
# 打印结果如图2,打印出来了

# 第三个参数里面的re.I可以忽略大小写
# 还有一个就是re.S,匹配所有字符包括换行符!!!

# 看例子
import re
lanuage = 'pythonC#\njavaphp'
r = re.findall('c#.{1}',lanuage,re.I)#c#.{1}表示首先匹配c#任意的一个字符,包括换行符
print(r)
# 这样什么都打印不出来。正确的结果如下图
import re
lanuage = 'pythonC#\njavaphp'
r = re.findall('c#.{1}',lanuage,re.I | re.S)#c#.{1}表示首先匹配c#任意的一个字符,包括换行符,re.S,匹配所有字符包括换行符!!!
print(r)
# 打印结果如图3
# re.I | re.S(这是且的关系,既要忽略大小写,又要支持对点号行为的改变,两个同时满足,若果有需要,可以加竖线然后后面接着写)

image
image
image

10-11 re.sub正则替换

# 10-11 re.sub正则替换
# 正则表达式中,并不是仅仅只有re一个模块,本章介绍re.sub
# 看例子

# re.findall用于查找,今天所讲的re.sub用于替换
import re
lanuage = 'pythonC#javaphp'
r = re.sub('C#','GO',lanuage)#注意re.sub的几个参数的意义
print(r)
# 打印结果如图1

import re
lanuage = 'pythonC#javaC#phpC#'
r = re.sub('C#','GO',lanuage,0)#注意re.sub的0的意义表示无限制的匹配下去,不管多少C#,全部都会被替换
print(r)
# 打印结果如图2

import re
lanuage = 'pythonC#javaC#phpC#'
r = re.sub('C#','GO',lanuage,1)#注意re.sub的1的意义表示只有字符串中第一个C#会被替换
print(r)
# 打印结果如图3

# 看看下面的替换方法
import re
lanuage = 'pythonC#javaC#phpC#'
lanuage.replace('C#','GO')
print(lanuage)
# 打印结果如图4,发现并没有实现替换!原因是字符串是不可变得,lanuage.replace('C#','GO')需要接收一下变量
# lanuage = lanuage.replace('C#','GO')即可

# re.sub强大的地方是第二个参数可以是个函数:看下面例子
import re
lanuage = 'pythonC#javaC#phpC#'
def convert(value):
    pass
r = re.sub('C#',convert,lanuage)
print(r)
# 打印结果如图5,C#消失不见了,是因为被函数里的空字符串替代了

# 继续看例子
import re
lanuage = 'pythonC#javaC#phpC#'
def convert(value):
    return '!!' + value + '!!'
r = re.sub('C#',convert,lanuage)
print(r)
# 打印结果如图6,出现了报错,下面分析一下报错的原因:
import re
lanuage = 'pythonC#javaC#phpC#'
def convert(value):#字符串并不会直接传到convert里面
    print(value)
    #return '!!' + value + '!!'
r = re.sub('C#',convert,lanuage)
print(r)
# 打印结果如图7

# 看看正确的代码:
import re
lanuage = 'pythonC#javaC#phpC#'
def convert(value):#字符串并不会直接传到convert里面
    matched = value.group()#拿到匹配结果
    return '!!' + matched + '!!'
r = re.sub('C#',convert,lanuage)
print(r)
# 打印结果如图8,成功打印

image
image
image
image
image
image
image
image

10-12 把函数作为参数传递

# 10-12 把函数作为参数传递
# Q1:有一个字符串,找出里面所有的数字,凡是大于6的,全部替换成9,凡是小于6的,全部替换成0
import re 
s = 'A8C3721D86'

def convert(value):
    matched = value.group()
    if matched >=6:
        return 9
    else:
        return 0

r = re.sub('\d',convert,s)#首先拿到数字
print(r)
# 打印结果如图1,是报错的

# 正确的如下:
import re 
s = 'A8C3721D86'

def convert(value):
    matched = value.group()
    if int(matched) >=6:
        return '9'
    else:
        return '0'

r = re.sub('\d',convert,s)#首先拿到数字
print(r)
# 打印结果如图2,正确的

image
image

10-13 search与match函数

# 10-13 search与match函数

# findall  search  match,参数都是一样的,来看看match和search之间的不同
import re 
s = 'A8C3721D86'
r = re.match('\d',s)
print(r)
# 打印结果如图1,没有匹配到结果

# 看看search
import re 
s = 'A8C3721D86'
r = re.search('\d',s)
print(r)
# 打印结果如图2,匹配到一个结果
# 导致返回结果不同的原因是:match是从首字母匹配的,search是全部搜索型的!!!,若将字符串第一个字母去掉
# 他们的输出结果是一样的

# 拿到返回结果
import re 
s = '8C3721D86'
r = re.search('\d',s)
print(r.group())
# 打印结果如图3

import re 
s = '8C3721D86'
r = re.match('\d',s)
print(r.span())#返回结果的位置
# 打印结果如图4

# findall会将所有的数字都打印出,这就是三者的不同点!

image
image
image
image

10-14 group分组

# 10-14 group分组

# Q1:下面的字符串,如何提取life和Python之间的字母?
import re
s = 'life is short ,i use python'
r = re.search('(life.*python)',s)#点和星号的作用10-4中有讲
print(r.group())#group的意义在于获得一个分组的匹配,group里面的一个分组0,可以省略!!
# group(0)是一个特殊的匹配结果,返回的都是完整的结果
# 打印结果如图1

import re
s = 'life is short ,i use python'
r = re.search('life(.*)python',s)
print(r.group(1))#group填写1,从1开始接收返回结果
# 打印结果如图2

#看看search和findall之间进行比较

import re
s = 'life is short ,i use python'
r = re.findall('life(.*)python',s)
print(r)
# 打印结果如图3

# 看看多个分组的情况!!!!
# Q2:下面的字符串,如何提取life和Python以及Python和Python之间的字母?
import re
s = 'life is short ,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.group(0))#group填写0
print(r.group(1))#group填写1
print(r.group(2))#group填写2
# 打印结果如图4

# 上述情况和下面的是一样的
import re
s = 'life is short ,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.group(0,1,2))
# 打印结果如图5

# 看看groups的情况吧
import re
s = 'life is short ,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.groups())#groups不会返回完整的结果,只会返回要匹配的中间结果!也就是括号括起来的结果
# 打印结果如图6

image
image
image
image
image
image

0-15 一些关于学习正则的建议
10-16 理解JSON
什么是JSON?
JavaScript Object Notation
JavaScript对象标记
JSON:是一种轻量级的数据交换格式
易于阅读
易于解析
网络传输效率高
跨语言交换数据

10-17 反序列化

# 10-17 反序列化
# Q1:把已知的字符串转换成我们熟悉的Python字符串?(这个过程叫做反序列化)

import json
json_str = '{"name":"xiaoyu","age":18}' #json格式要求字符串必须加双引号
student = json.loads(json_str)
print(type(student))
print(student)
# 打印结果如图1所示,是字典的形式

import json
json_str = '{"name":"xiaoyu","age":18}' 
student = json.loads(json_str)
print(type(student))
print(student)
print(student['name'])
print(student['age'])#通过这种访问方式可以非访问json中,我们想要的结果
# 打印结果如图2所示
# json的数据格式类型是对象形式,转换成Python里的字典数据类型
# json的数据格式类型是数组形式,转换成Python里的什么数据类型???看代码!!(答案是列表类型)
import json
json_str = '[{"name":"xiaoyu","age":18},{"name":"xiaoyu","age":18}]' #json的数组类型
student = json.loads(json_str)
print(type(student))
print(student)
# 打印结果如图3 4所示,是列表的形式

#还有bool类型的情况
import json
json_str = '[{"name":"xiaoyu","age":18,"flag":false},{"name":"xiaoyu","age":18}]' #json的数组类型
student = json.loads(json_str)
print(type(student))
print(student)
# 打印结果如图5,结果是大写的false

# json有自己的数据类型,我们用json.loads函数把json数据类型转换成我们所需要的类型。这个过程叫做反序列化

10-18 序列化

# 10-18 序列化
# 左边是json格式类型对应到右边的Python格式类型
json                python 
object              dict
array               list
string              str
number              int 
number              float 
true                True 
false               False 
null                None 

# 看看序列化的过程,就是把Python的数据类型转换成json的数据类型
# Q1:把Python中的字典类型转换成json里的形式?

import json
student = [
            {'name':'xiaoyu','age':18,'flag':False},
            {'name':'xiaoyu','age':18}

        ]
json_str = json.dumps(student)#json.dumps序列化的过程
print(type(json_str))
print(json_str)
# 打印结果如图1,就是json格式

image

10-19 小谈JSON、JSON对象与JSON字符串

10-19 小谈JSON、JSON对象与JSON字符串

JSON:数据交换格式

JSON对象

image
image

作者:buaishengqi
链接:https://www.jianshu.com/p/dd37dc147f4a
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容