正则表达式

一 介绍

拼正则表达式是什么?

  • 它是约束字符串匹配某种形式的规则

正则表达式有什么用?

  1. 检测某个字符串是否符合规则比如:判断手机号,身份证号是否合法
  2. 提取网页字符串中想要的数据.比如:爬虫中,提取网站天气,信息,股票代码,星座运势等具体关键字

线测试工具http://tool.chinaz.com/regex

正则表达式由一些[普通字符]和一些[元字符]组成:

(1)普通字符包括大小写字母和数字

(2)元字符具有特殊含义,大体种类分为如下

  1. 预定义字符集,字符组
  2. 量词
  3. 边界符
  4. 分组

二 正则表达式findall

2.1 单字符匹配

findall("正则表达式","要匹配的字符串")

\d 和 \D

  • \d 匹配数字
  • \D 匹配非数字
import re
lst = re.findall("\d","davfdardwer24523`de3r43wqe#$@!dwd@#!2143DC")
print (lst)
lst = re.findall("\D","davfdardwer24523`de3r43wqe#$@!dwd@#!2143DC")
print (lst)

执行

[root@node10 python]# python3 test.py
['2', '4', '5', '2', '3', '3', '4', '3', '2', '1', '4', '3']
['d', 'a', 'v', 'f', 'd', 'a', 'r', 'd', 'w', 'e', 'r', '`', 'd', 'e', 'r', 'w', 'q', 'e', '#', '$', '@', '!', 'd', 'w', 'd', '@', '#', '!', 'D', 'C']

\w和\W

  • \w 匹配字母数字下换线 (正则函数中,支持中文匹配)
  • \W 匹配非字母,数字,下划线
import re
lst = re.findall("\w","dwer_=\|:';.你好世界24523`de3re#$@!dwd@#!2143DC")
print (lst)
lst = re.findall("\W","dwer_=\|:';.你好世界24523`de3re#$@!dwd@#!2143DC")
print (lst)

执行

'd', 'w', 'e', 'r', '_', '你', '好', '世', '界', '2', '4', '5', '2', '3', 'd', 'e', '3', 'r', 'e', 'd', 'w', 'd', '2', '1', '4', '3', 'D', 'C']
['=', '\\', '|', ':', "'", ';', '.', '`', '#', '$', '@', '!', '@', '#', '!']

\s和\S

  • \s 匹配任意的空白符(\n \t)
  • \S 匹配任意的非空白符
import re
strvar = ' '
lst = re.findall("\s",strvar)
print(lst)
strvar = " 8989sdf 111"
lst = re.findall("\S",strvar)
print(lst)

执行

[root@node10 python]# python3 test.py
[' ', '\t', '\t', '\t', '\t', '\t']
['8', '9', '8', '9', 's', 'd', 'f', '1', '1', '1']

\n和\t

  • \n 匹配一个换行
  • \t 匹配一个缩进
import re
strvar = """
sdfsd sdfsdf sfsdfsdf
sdfsddffg dfgdfg fgdfg
"""
lst = re.findall("\n",strvar)
print(lst)
lst = re.findall("\t",strvar)
print(lst)

字符组 [123]

[123] 必须从字符组当中挑出一个出来,个数上有要求,必须一个,如果匹配不到就是空.

import re
lst = re.findall("[123]","sdfs3fkj5kj")
print(lst) print(re.findall('a[abc]b','aab abb acb adb'))

执行

[root@node10 python]# python3 test.py
['3']
['aab', 'abb', 'acb']

字符组

import re
# [0123456789] => [0-9] -是一个特殊字符,代表范围0-9 0到9
print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb'))
print(re.findall("a[0-9]b",'a1b a2b a3b acb ayb')) #[abcdefg] => [a-g] 表达所有小写字符可以用[a-z]
print(re.findall('a[a-z]b','a1b a2b a3b acb ayb adb')) #['acb', 'ayb', 'adb']
# print(re.findall('a[abcdefg]b','a1b a2b a3b acb ayb adb')) #['acb', 'adb'] # [ABCDEFG] A-G [A-Z]用来表达所有大写字符
print(re.findall('a[A-Z]b','a1b a2b a3b aAb aDb aYb')) #['aAb', 'aDb', 'aYb']
print(re.findall('a[ABCDEFG]b','a1b a2b a3b aAb aDb aYb')) #aAb aDb print(re.findall('a[0-9a-zA-Z]b','a-b aab aAb aWb aqba1b')) #['aab', 'aAb', 'aWb', 'aqb', 'a1b']
print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b')) #['a1/b']
# 字符组当中的^ 代表除了的意思
# 除了+ - * / 这些字符之外,剩下的都能匹配
print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd")) #['a%b', 'a&b']
# 在特殊字符前面加商一个\,让原本有意义的字符变得无意义,用于正则字符匹配
print(re.findall('a[\^]b',"a^b")) #['a%b', 'a&b']

执行

[root@node10 python]# python3 test.py
['a1b', 'a2b', 'a3b']
['a1b', 'a2b', 'a3b']
['acb', 'ayb', 'adb']
['aAb', 'aDb', 'aYb']
['aAb', 'aDb']
['aab', 'aAb', 'aWb', 'aqb', 'a1b']
['a1/b']
['a%b', 'a&b']
['a^b']

2.2 正则匹配多个字符

量词

import re
'''1) ? 匹配0个或者1个a '''
print(re.findall('a?b','abbzab abb aab'))
'''2) + 匹配1个或者多个a '''
print(re.findall('a+b','b ab aaaaaab abb'))
'''3) * 匹配0个或者多个a '''
print(re.findall('a*b','b ab aaaaaab abbbbbbb'))
'''4) {m,n} 匹配m个至n个a '''
print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb'))

执行

[root@node10 python]# python3 test.py
['ab', 'b', 'ab', 'ab', 'b', 'ab']
['ab', 'aaaaaab', 'ab']
['b', 'ab', 'aaaaaab', 'ab', 'b', 'b', 'b', 'b', 'b', 'b']
['aaab', 'ab', 'aab', 'ab', 'aab']

2.3 贪婪匹配 和 非贪婪匹配

贪婪匹配:

  • 默认向更高次数匹配,程序当中默认使用贪婪匹配

非贪婪匹配:

  • 默认向更少次数匹配
  • 语法:只需要在量词的后面再加上一个?号

底层用的时回溯算法:
从左到右开始寻找,直到找到最后再也找不到了,回头,找离右侧最近的那个值返回

import re
strvar = "刘能和刘罗锅和刘备有3儿子4"
#.表示除了\n以外的任意字符
lst = re.findall("刘.",strvar)
print (lst)
#.?表示刘后的字符可以出现1次或者多个
lst = re.findall("刘.?",strvar)
print(lst)
#.+表示刘后的的任意字符出现0个或者多个
lst = re.findall("刘.+",strvar)
print(lst)
lst = re.findall("刘.*",strvar)
print(lst)
lst = re.findall("刘.*子",strvar)
print(lst)
lst = re.findall("刘.{1,20}",strvar)
print(lst)
lst = re.findall("刘.{1,20}子",strvar)
print(lst) print("非贪婪匹配")
lst = re.findall("刘.??",strvar)
print(lst)
lst = re.findall("刘.+?",strvar)
print(lst)
lst = re.findall("刘.*?",strvar)
print(lst)
lst = re.findall("刘.*?子",strvar)
print(lst)
lst = re.findall("刘.{1,20}?",strvar)
print(lst)
# 默认使用的是贪婪模式,一直找到最后一个子,如果使用非贪婪,找到第一个字就立刻返回.
lst = re.findall("刘.{1,20}?子",strvar)
print(lst)

执行

['刘能', '刘罗', '刘备']
['刘能', '刘罗', '刘备']
['刘能和刘罗锅和刘备有3儿子4子']
['刘能和刘罗锅和刘备有3儿子4子']
['刘能和刘罗锅和刘备有3儿子4子']
['刘能和刘罗锅和刘备有3儿子4子']
['刘能和刘罗锅和刘备有3儿子4子']
非贪婪匹配
['刘', '刘', '刘']
['刘能', '刘罗', '刘备']
['刘', '刘', '刘']
['刘能和刘罗锅和刘备有3儿子']
['刘能', '刘罗', '刘备']
['刘能和刘罗锅和刘备有3儿子']

2.4 边界符\b ^ $

例:\b \bw 以w作为左边界  d\b 以d作为右边界

\b 它默认是一个转义字符 退格 backspace
需要通过字符串前面加上r,让转义字符失效,呈现正则的含义.

import re
#只匹配右边界d
lst = re.findall(r"d\b","word pwd abc")
print(lst)
#匹配右边界前的任意字符
lst = re.findall(r".*d\b","word pwd abc")
print(lst)
# 能够匹配到一个右边界d ,就立刻返回
# .可以匹配空白符,除了\n,剩下所有字符都能匹配到
lst = re.findall(r".*?d\b","word pwd abc")
print(lst)
#匹配到非空白符
lst = re.findall(r"\S*?d\b","word pwd abc") # 纯单词,舍去空格
print(lst)
#匹配以w开头的非空白符
lst = re.findall(r"\bw\S*","word pwd abc") #'word'
print(lst)

执行

[root@node10 python]# python3 test.py
['d', 'd']
['word pwd']
['word', ' pwd']
['word', 'pwd']
['word']

2.5 使用^$

  • 如果使用了^ 或者 $
  • ^ : 必须以某个字符开头,后面剩下的无所谓
  • $ : 必须以某个字符结尾,前面剩下的无所谓
  • 意味着把这个字符串当成一个整体
import re
strvar = "大哥大嫂大爷"
print ("匹配大后面出\\n的任意字符")
print(re.findall('大.',strvar))
print ("匹配以大开头后面出\n的任意字符,同时把这个字符串看成一个整体")
print(re.findall('^大.',strvar)) # 只匹配一个,把字符串开成整体
print ("必须以一个任意字符结尾")
print(re.findall('大.$',strvar)) # 只匹配一个,把字符串开成整体
# strvar = "大书"
print ("以大开头,以任意字符结尾的两个字符,为空")
print(re.findall('^大.$',strvar))
print ("以大开头,匹配.*,?只是非贪婪匹配")
print(re.findall('^大.*?$',strvar))
print ("以g开头,匹配到空格停止")
print(re.findall('^g.*? ' , 'giveme 1gfive gay'))
print ("以e结尾,向前找到five,打出 ")
print(re.findall('five$' , 'aassfive'))
print ("以c结尾,匹配abc打印")
print(re.findall("abc$","abcabcabc"))
print ("全部卡死")
print(re.findall('^giveme$' , 'giveme'))
print ("完全卡死,并不匹配,返回空")
print(re.findall('^giveme$' , 'giveme giveme'))
print ("以g开头,e结尾,中间匹配任意")
print(re.findall('^g.*?e$' , 'giveme giveme'))
print ("匹配giveme,有两个")
print(re.findall('giveme' , 'giveme giveme'))
print ("以g开头,卡到e")
print(re.findall("^g.*e",'giveme 1gfive gay'))
print ("以g开头,卡到e,并使用非贪婪匹配")
print(re.findall("^g.*?e",'giveme 1gfive gay'))

执行

[root@node10 python]# python3 test.py
匹配大后面出\n的任意字符
['大哥', '大嫂', '大爷']
匹配以大开头后面出
的任意字符,同时把这个字符串看成一个整体
['大哥']
必须以一个任意字符结尾
['大爷']
以大开头,以任意字符结尾的两个字符,为空
[]
以大开头,匹配.*,?只是非贪婪匹配
['大哥大嫂大爷']
以g开头,匹配到空格停止
['giveme ']
以e结尾,向前找到five,打出
['five']
以c结尾,匹配abc打印
['abc']
全部卡死
['giveme']
完全卡死,并不匹配,返回空
[]
以g开头,e结尾,中间匹配任意
['giveme giveme']
匹配giveme,有两个
['giveme', 'giveme']
以g开头,卡到e
['giveme 1gfive']
以g开头,卡到e,并使用非贪婪匹配
['give']

2.6 正则表达式分组匹配

正常分组

  1. 正常情况下用()圆括号进行分组 可以用\1 反向引用第一个圆括号匹配的内容。
  2. (?:正则表达式) 表示取消优先显示的功能
import re
print("匹配所有_good前的任意字符打印出")
print(re.findall('.*?_good','wusir_good alex_good xboyww_good'))
print("匹配所有的姓名")
print(re.findall('(.*?)_good','wusir_good alex_good xboyww_good'))
print("匹配所有的姓名,然后取消分组")
print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))

执行

[root@node10 python]# python3 test.py
匹配所有_good前的任意字符打印出
['wusir_good', ' alex_good', ' xboyww_good']
匹配所有的姓名
['wusir', ' alex', ' xboyww']
匹配所有的姓名,然后取消分组
['wusir_good', ' alex_good', ' secret男_good']

a|b 匹配字符a 或者 匹配字符b  把字符串长的写在前面,字符串短的写在后面

  • | 代表或的意思
import re
res = re.findall("abcd|abc","abcdabcdabcd abc")
print(res)

执行

[root@node10 python]# python3 test.py
['abcd', 'abcd', 'abcd', 'abc']

2.7 匹配小数

import re
strvar = " 3.14 .34 35. ... 2.41.3 34.."
res = re.findall("\d+\.\d+",strvar)
print(res)

执行

[root@node10 python]# python3 test.py
['3.14', '2.41']

匹配小数和整数

import re

strvar = "3.15 34 .. 3434.23.234.2323 .34.34 .3434 .. .. nihao"
res = re.findall("\d+\.\d+|\d+",strvar)
print(res)

执行

[root@node10 python]# python3 test.py
['3.15', '34', '3434.23', '234.2323', '34.34', '3434']

优化版

findall 这个函数默认优先显示小括号里面的内容,如果不想显示,用?:
小括号代表的是分组,放到一起代表整体,这个例子要么出现小数点和后面的值,要么不出现.

import re

strvar = "3.15 34 .. 3434.23.234.2323 .34.34 .3434 .. .. nihao"
res = re.findall("\d+(?:\.\d+)?",strvar)
print(res)

执行

[root@node10 python]# python3 test.py
['3.15', '34', '3434.23', '234.2323', '34.34', '3434']

匹配135或171的手机号

import re
res = re.findall("(?:135|171)\d{8}","13588889897 17180668088")
print(res)

执行

[root@node10 python]# python3 test.py
['13588889897', '17180668088']

正则要求卡主开头和结尾,且长度是11位 (这个例子开头结尾满足,但长度不对)

import re
res = re.findall("(?:^135|^171)\d{8}$","13588889897 17180668088")
print(res)

执行

[root@node10 python]# python3 test.py
[]

#(?:     ^135      |      ^171     )

import re
res = re.findall("(?:^135|^171)\d{8}$","17188889897")
print(res)

执行

[root@node10 python]# python3 test.py
['17188889897']

三 search 正则方法

3.1 介绍

search("正则表达式","要匹配的字符串")
它返回的是一个对象

  • 对象.属性
  • 对象.方法()
  • 想要获取对象里面的值用group()方法
  • 想要获取分组里面的值用groups()方法

和 findall区别

  1. findall 找出所有匹配的结果,从左到右,返回的是列表
  2. search 找出一个结果就返回,从左到右,返回的是对象
import re
obj = re.search("\d+","ksj323rf33sdf*&*& 78787878")
print(obj)
res = obj.group()
print(res)

执行

[root@node10 python]# python3 test.py
<_sre.SRE_Match object; span=(3, 6), match='323'>
323

3.2 基本使用

匹配www.baidu.com 或者 www.google.com

import re
obj = re.search("(www).(baidu|google).(com)","www.baidu.com www.google.com")
res = obj.group()
#通过group拿到实际匹配的内容
print(res)
#通过groups拿到小括号里面匹配的内容
res = obj.groups()
print(res)

执行

[root@node10 python]# python3 test.py
www.baidu.com
('www', 'baidu', 'com')

同一时间,既可以拿到匹配的结果,又可以拿到小括号里的内容,而findall不具备

findall 同一时间只能拿取一种结果,要么是实际匹配的,要么是小括号的.

search 只能匹配一个, findall 可以匹配所有. 这是两个函数之间的差别.

import re
obj = re.search("(www).(baidu|google).(com)","www.baidu.com www.google.com")
res = obj.group()
print(res) #www.baidu.com
res = obj.groups()
print(res)
res = re.findall("(www).(baidu|google).(com)","www.baidu.com www.google.com")
print(res)

执行

[root@node10 python]# python3 test.py
www.baidu.com
('www', 'baidu', 'com')
[('www', 'baidu', 'com'), ('www', 'google', 'com')]

3.3 对比两个函数区别

匹配出5*4 或者 6/8

import re
strvar = "5*4+6/8"
obj = re.search("\d+[*/]\d+",strvar)
# 获取对象当中的值
res = obj.group()
print(res) res= re.findall("\d+[*/]\d+",strvar)
print(res)

执行

[root@node10 python]# python3 test.py
5*4
['5*4', '6/8']

一般有分组的情况下用search 更多,找到所有匹配条件一般用findall

035.Python正则表达式的更多相关文章

  1. Python 正则表达式入门(中级篇)

    Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...

  2. Python正则表达式中的re.S

    title: Python正则表达式中的re.S date: 2014-12-21 09:55:54 categories: [Python] tags: [正则表达式,python] --- 在Py ...

  3. Python 正则表达式入门(初级篇)

    Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...

  4. python正则表达式re

    Python正则表达式: re 正则表达式的元字符有. ^ $ * ? { [ ] | ( ).表示任意字符[]用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字符集,对于字符集中的字符可 ...

  5. Python正则表达式详解

    我用双手成就你的梦想 python正则表达式 ^ 匹配开始 $ 匹配行尾 . 匹配出换行符以外的任何单个字符,使用-m选项允许其匹配换行符也是如此 [...] 匹配括号内任何当个字符(也有或的意思) ...

  6. 比较详细Python正则表达式操作指南(re使用)

    比较详细Python正则表达式操作指南(re使用) Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式.Python 1.5之前版本则是通过 regex 模块提供 E ...

  7. Python正则表达式学习摘要及资料

    摘要 在正则表达式中,如果直接给出字符,就是精确匹配. {m,n}? 对于前一个字符重复 m 到 n 次,并且取尽可能少的情况 在字符串'aaaaaa'中,a{2,4} 会匹配 4 个 a,但 a{2 ...

  8. python正则表达式 小例几则

    会用到的语法 正则字符 释义 举例 + 前面元素至少出现一次 ab+:ab.abbbb 等 * 前面元素出现0次或多次 ab*:a.ab.abb 等 ? 匹配前面的一次或0次 Ab?: A.Ab 等 ...

  9. Python 正则表达式-OK

    Python正则表达式入门 一. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分. 正则表达式是用于处理字符串的强大工具, 拥有自己独特的语法以及一个独立的处理引擎, 效率上 ...

随机推荐

  1. python基础(三):元组

    什么是元组 有时候你需要创建一系列不可修改的元素,元组可以满足这种需求.Python将不能修改的值称为不可变的,而不可变的列表被称为元组. 元组的定义和访问 元组使用圆括号来定义,我们已经知道:元组也 ...

  2. (文字版)Qt信号槽源码剖析(三)

    大家好,我是IT文艺男,来自一线大厂的一线程序员 上节视频给大家讲解了Qt信号槽的Qt宏展开推导:今天接着深入分析,进入Qt信号槽源码剖析系列的第三节视频. Qt信号槽宏推导归纳 #define si ...

  3. buuctf pwn wp---part1

    pwn难啊 1.test_your_nc 测试你nc,不用说,连上就有. 2.rip ida中已经包含了system函数: 溢出,覆盖rip为fun函数,peda计算偏移为23: from pwn i ...

  4. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之vmware设置-02

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria之vmware设置-02 欢迎加QQ群:1026880196  进行讨论 1. vmwae版本 2. 网 ...

  5. Spring Boot demo系列(二):简单三层架构Web应用

    2021.2.24 更新 1 概述 这是Spring Boot的第二个Demo,一个只有三层架构的极简Web应用,持久层使用的是MyBatis. 2 架构 一个最简单的Spring Boot Web应 ...

  6. java中的|=符号

    今天看mybaits源码的时候,发现了这个特殊的符号用法,|=. for (ParameterMapping pm : boundSql.getParameterMappings()) { Strin ...

  7. Redis系统学习之SpringBoot集成Redis操作API(集成SpringDataRedis及其分析)

    SpringDataRedis调用Redis底层解读 在SpringBoot2.X之前还是直接使用的官方推荐的Jedis连接的Redis 在2.X之后换为了lettuce Jedis:采用直接连接,多 ...

  8. 【Unity】实验二 游戏场景搭建

    实验要求 实验二 游戏场景搭建 实验目的:掌握游戏场景搭建. 实验要求:能够使用Unity的地形引擎创建地形,熟悉场景中的光照与阴影,掌握天空盒和雾化效果等. 实验内容: 地形的绘制:使用高度图绘制: ...

  9. ppt技巧--线条

    声明:本文所有截图来源于网易云课堂--<和秋叶一起学PPT>,只做个人复习之用,特此声明! 线条的五种用途:

  10. 基于queue的python多进程日志管理

    在我们的异常检测应用中,需要对每组IoT设备分别训练一个模型,每个模型对一组设备的指标数据进行实时异常检测.方案采用master-worker+消息队列的方式实现模型对外服务,但是每个worker的日 ...