一. 正则表达式

1. 匹配次数相关的正则符号

a.   '+'       一次或多次(至少一次) ,控制+ 前面元素的次数,看下面事例
from re import fullmatch

'''
a+      至少一个a ,
\d+     至少一个数字字符

'''
result = fullmatch(r'1a+2','1aaaaaaaa2') #1和2中间至少要有一个a
print(result)

result = fullmatch(r'1\d+2','1454454545452') #1和2之间至少要有一个数字字符
print(result)

result = fullmatch(r'1[A-Z]+2','1DFER2')
print(result)
b.  ' * '  任意次数 
result = fullmatch(r'1a*2','12') #和 + 唯一区别是, 可以一个元素都没有
print(result) # 1和2之间可以任意个a,可以没有a
c.  ' ? '     ---  0次或者1次, 最多一次
result = fullmatch(r'1[\u4e00-\u9fa5]?2','1吗2') #1 和2之间0或1个中文字符
print(result)
d.   { }   

        { N }  N次

      { M,N }  M到N次

       {M,}.     至少M次

        { ,N } 最次

result = fullmatch(r'1[3-9]\d{3}','13111') #\d任意数字字符只能三次
print(result)


result = fullmatch(r'1[3-9]\d{3,5}','1311111')#\d任意数字字符可以出现3次到5次(3,5也行)
print(result)


result = fullmatch(r'1[3-9]\d{3,}','13111') # 最少3次
print(result)

result = fullmatch(r'1[3-9]\d{,3}','1311') #最多三次,这里是两次
print(result) 

2. 贪婪和非贪婪

  1.定义:
  • 如果在正则表达式中有不确定的匹配次数,这个正则在匹配字符串的时候可以分为贪婪和非贪婪两种模式
  2. 贪婪(默认)
  • 定义:如果一个字符串和正则进行匹配的时候有多种情况可以匹配成功,贪婪取最多的那个次数进行匹配
    3.非贪婪( +?, *?, ??, {M,N}?, {M,}?, {,N}? )
  • 定义:如果一个字符串恶和正则进行匹配时有多种情况可以匹配成功,非贪婪取最少的那个次数进行匹配
result = match(r'a[a-z]+?b','amnbdfdfbdfdfdfbd')
print(result)

#这样只会选择amnb, +? 是取最小的满足匹配规则的

3. match 和 fullmatch

   match(正则表达式, 字符串)   --- 匹配字符串开头
result = match(r'\d{3}','123的粉红色答复哈水电费哈水淀粉')
print(result)
#只匹配开头123,后面多少都可以


# 注意
result = match(r'a[a-z]+b','amnbdfdfbdfdfdfbd')
print(result)
#首先默认贪婪, 这里是a和b中间可以任意a-z字母, 但是后面这种有很多选择,amnb可以
#amnbdfdfb可以

4. 其他符号 

   1. 分组      ()
  • a. 整体操作: 将正则表达式中的一部分内容用 () 括起来表示一个整体
result = fullmatch(r'(\d\d[a-z]{3}){3}','99qwe44ewq35oer')
print(result) 
#( )括号括起来的一部分是一个整体,两个数据+三个字母 重复三次



result = fullmatch(r'(\d[A-Z])+abc','2W8Jabc')
print(result)
# 这里是  任意数字和任意大写字母的一个组合,可以重复多次, 最后加上 abc 
  • b. 重复    - 在正则表达式中可以用 \N  来重复 \N前面的第N个分组匹配到的内容
result = fullmatch(r'(\d{3})([A-Z]{2})=\2\1{3}','123AD=AD123123123')
print(result)


'''
 先任意数字字符三个,选择123
 然后任意一个大写字母,选择两个 AD
 再来一个 = 
 再\2 第二个分组也就是 选个字母 执行两次 ,再来一个AD
 再是\1{3} , 就是第一个分组, \d{3} 执行3次 ,也就是123 再写3次


'''
  •    c. 捕获 :获取匹配结果的时候只获取正则表达式中某个分组匹配到的内容

                1.自动捕获:findall 函数支持自动捕获(findall在获取匹配结果的时候自动获取分组匹配到的结果)      

       findall(正则表达式, 字符串)  ---  获取字符串所有符合正则表达式所描述的规则子串     

result = findall(r'\d{3}','123AD=AD1231dfer231ddd23')
print(result) #找三个连续数字字符
#['123', '123', '231']


# 提取  前面要有中文字符的连续三个数字
result = findall(r'[\u4e00-\u9fa5](\d{3})','的123AD=AD大方123dfer的f231ddd23')
print(result) # 将三个连续字符这个要求用 () 分组 框起来,就只获取分组中内容
#['123', '123']

                  2.手动捕获: fullmatch 、match、search、finditer的结果都支持手动捕获   

  • match        
result = match(r'([\u4e00-\u9fa5])(\d{3})','的123AD=AD大方123dfer的f231ddd23')
print(result.group(1),result.group(2),result.group())

# 的 123 的123
'''
result.group() 是输出你所要求的部分, 这里就是汉字+三个数字。汉字是第一个分组(括号括起来的)
result.group(1) 是你要求的部分且用分组符号括起来的, 就是汉字
result.group(2)  第二部分,就是 三个连续数字 
'''
2. 分支        ' | '
  • 语法: 正则1|正则2       理解为 or ,先让正则1和字符串匹配,如果失败再用正则2和字符串进行匹配(两个正则中只要有一个匹配成功就成功)
result = fullmatch(r'\d{3}abc|[A-Z]{3}abc','QWEabc')
print(result) 
# 这是三个数字+abc 或 三个大写字母+abc都可



result = fullmatch(r'(\d{3}|[A-Z]{3})abc','123abc')
print(result)

# 用 分组() 框起来的部分,+abc , 分组中的 | 前后满足其一即可,最后是abc
3. 转义字符      在有特殊意义的符号前面加 \ , 让其功能消失变成一个普通符号。 注意:单独存在有特殊意义(除了\d  \s  \w等)的符号放在[ ]里面他的功能也会消失,变成普通符号 ( ‘-’ 号只能放在最前或最后面,其他地方要加  \- ,    ^ 也是)
result = fullmatch(r'\d\d\.\d\d','23.55')
print(result)
# 想让一个小数进行匹配, 因为 . 在正则中是匹配任意字符功能,加个 \ ,让其功能消失

result = fullmatch(r'\d\d[.]\d\d','23.45')
print(result)


result = fullmatch(r'\(\d{3}\)','(183)')
print(result)


# 放在[] 里 符号失去功能
result = fullmatch(r'[.+?*(){}]abc','{abc')
print(result)
4. 检测类符号      (先匹配,如果匹配成功再检测,检测类所在的位置是否符合要求)
  • ^      - 检测是否是字符串开头(只能放在正则的开头)
  • $      - 检测是否字符串结尾(只能放在结尾)
  • \b     - 检测是否是单词边界(凡事可将两个英文单词区分开的符号都是单词边界:空白、英文标点符号、字符串开头和结尾)
  • \B     - 检测是否不是单词边界(board)
result = fullmatch(r'\d{3}\s\babc','342 abc')
print(result)
#\s 在这是空格, \b 检测a前面是否是单词边界

5. re模块

     1. fullmatch 、 match、 search
  • fullmatch(正则表达式,字符串)     --- 完全匹配(让整个字符串进行匹配),如果匹配成功返回匹配对象,失败返回None
  • match(正则表达式,字符串)        --- 匹配字符串开头,如果匹配成功返回匹配对象,失败返回None
  • search(正则表达式,字符串)       --- 匹配字符串中第一个满足正则的子串,如果匹配成功返回匹配对象,失败返回None
     2.findall 、finditer
  • findall(正则表达式,字符串)     --- 获取字符串中所有满足正则表达式的子串,结果是个列表,列表内容是字符串(正则中如果有分组会自动捕获)
result = findall(r'\d{3}','是的343非454非地方934非地方地方ffdf343方法')
print(result)
#['343', '454', '934', '343']
  • finditer(正则表达式,字符串)    --- 获取字符串中所有满足正则表达式的子串,结果是一个是迭代器,迭代器中元素是匹配对象
result = finditer(r'\d{3}','是的343非454非地方934非地方地方ffdf343方法')
print(list(result))
'''
[<re.Match object; span=(2, 5), match='343'>,
 <re.Match object; span=(6, 9), match='454'>, 
<re.Match object; span=(12, 15), match='934'>,

'''
     3. splite(正则表达式,字符串)       
  • 将字符串所有满足正则的子串作为切割点对字符串进行切割
  • splite(正则表达式,字符串,N)    将字符串前N个满足正则的子串作为切割点对字符串进行切割
result = split(r'\d{3}','是的343非454非地方934非地方地方ffdf343方法')
print(result)


result = split(r'\d{3}','是的343非454非地方934非地方地方ffdf343方法',3)
print(result)
4.sub
  •       sub  (正则表达式,字符串1,字符串2)   将字符串2中所有满足正则的子串都换成字符串1

  •       sub  (正则表达式,字符串1,字符串2,N)   将字符串2中前N 个满足正则的子串都替换成字符串1
result = sub(r'\d{3}','+','是的343非454非地方934非地方地方ffdf343方法')
print(result)
# 把连续三个数字换成 +
#是的+非+非地方+非地方地方ffdf+方法


result = sub(r'\d{3}','+','是的343非454非地方934非地方地方ffdf343方法',2)
print(result)
# 只换前两个
#是的+非+非地方934非地方地方ffdf343方法
5.正则参数
   a.    1.  忽略大小写    匹配的时候让同一个字母的大写和小写相同

        r'(?i)正则表达式' 

result = fullmatch(r'(?i)[a-z]\d{3}','R345')
print(result)
       a.   2.  加参数  I (ignorecase)  from re import I   也是忽略大小写

        给正则函数 flags = I

result = fullmatch(r'[a-z]\d{3}','R345',flags= I)
print(result)
   b. 单行匹配 (默认是多行匹配)
  • 多行匹配时正则中的 ' . '不能和 \n 匹配, 单行匹配的时候正则中的 ' . ' 是可以和 \n 进行匹配的 , 加一个(?s) s是single 单行匹配

result =  fullmatch(r'(?s)a.b','a\nb')
print(result)
  • 或者给正则函数flags 赋值为S(re模块中的S)
result =  fullmatch(r'a.b','a\nb',flags=S)
print(result)
 如何做到 又忽略大小写 又转为单行匹配
# 用(?si)
result =  fullmatch(r'(?si)a.b','A\nb')
print(result)


# flags 参数赋值  S | I
result =  fullmatch(r'a.b','A\nb',flags=S|I)
print(result)

# flags参数给s 成单行匹配, 在前面(?i)忽略大小写
result =  fullmatch(r'(?i)a.b','A\nb',flags=S)
print(result)
02-02 11:32