1_正则表达式(python)

文章目录


介绍

python re 模块-正则- python 官方文档 中文

正则语法 python


书籍推荐


Jeffrey E. F. Friedl的《Mastering Regular Expressions》一书,
Michael Fitzgerald的《Introducing Regular Expressions》,
Jan Goyvaerts和Steven Levithan写的《Regular Expressions Cookbook》

都是O'Reilly出版社出版,这些书都非常受欢迎。


regex101 网站

regex101对于新手是特别有用的网站,可以自动生成正则表达式的解读。
在这里插入图片描述


正则表达式测试网站
在这里插入图片描述


正则可视化测试网站


正则表达式用于搜索替换解析 字符串。 正则表达式遵循一定的语法规则, 使用非常灵活, 功能强大。 使用正则表达式编写一些逻辑验证非常方便, 例如电子邮件地址格式的验证

正则表达式对字符串(包括普通字符(例如, a 到 z 之间的字母) 和特殊字符) 操作
的一种逻辑公式, 就是用事先定义好的一些特定字符、 及这些特定字符的组合, 组成一个“规 则字符串” , 这个“规则字符串” 用来表达对字符串的一种过滤逻辑, 正则表达式是一种文 本模式, 模式描述在搜索文本时要匹配一个或多个字符串。


一开始的例子 如果看不懂 可以先 跳过。
然后看 searchmatch 方法 。 接着 回过头来 看 常用匹配字符串

然后顺序往下看。

当然也可以根据自己的想法 ,随意观看。


例子


在这里插入图片描述

In [16]: import re

In [17]: pat=r'P(Y|YT|YTH|YTHO)?N'

In [18]: p=re.compile(pat) # 面向对象  编译 。 多次使用的正则
 
In [19]: p.findall("i love PN PYN PYTN PYTHN PYTHON PDADN")
Out[19]: ['', 'Y', 'YT', 'YTH', 'YTHO']

In [21]: p.search("i love PN PYN PYTN PYTHN PYTHON PDADN")
Out[21]: <_sre.SRE_Match object; span=(7, 9), match='PN'>

# 当然你也可以使用这种方式 单次 使用。
In [22]: re.findall(pat,"i love PN PYN PYTN PYTHN PYTHON PDADN")
Out[22]: ['', 'Y', 'YT', 'YTH', 'YTHO'] 

# ---------------------------

In [23]: pat=r'PYTHON+'

In [24]:  p=re.compile(pat)
In [25]: p.findall("PYTHONN PYTHONNNN PYTHONN PYTHON PYTHO")
Out[25]: ['PYTHONN', 'PYTHONNNN', 'PYTHONN', 'PYTHON']

# -------------------------------

In [27]: pat=r'PY[TH]ON'

In [28]: p=re.compile(pat)

In [29]: p.findall("PYTON PYHON PYTHON")
Out[29]: ['PYTON', 'PYHON']

# ------------------------------
# [^5] 将匹配除 '5' 以外的字符
# 那这里就是 匹配除了 TH以外的字符 中括号这个位置
# ? 表示0 次或者 1次
In [30]: pat=r'PY[^TH]?ON'

In [31]: p=re.compile(pat)

In [34]: p.findall("PYON PYaON PYTHON PYcON PYTON PYAON")
Out[34]: ['PYON', 'PYaON', 'PYcON', 'PYAON']

# -------------------
In [35]: pat='PY{0,3}N'
# 图片中的写法 {:3} 这种写法 不生效 无法匹配

In [36]: p=re.compile(pat)

In [37]: p.findall("PYNPYNPYNPYN PYYN PYYYN PYYYYYN")
Out[38]: ['PYN', 'PYN', 'PYN', 'PYN', 'PYYN', 'PYYYN']

在这里插入图片描述

In [37]: pat=r'^[A-Za-z]+$' # 既然 + 是 1 次或者无限次
# 那么 我们也可以改为  ? 0次 或者 1次 那就只匹配 1个 字母了
# 字母
In [38]: p=re.compile(pat)

In [39]: p.match("adsfadfasd")
Out[39]: <_sre.SRE_Match object; span=(0, 10), match='adsfadfasd'>

In [40]: p.match("adsfadfasdADSFAKSD...")

In [41]: p.match("adsfadfasdADSFAKSD")
Out[41]: <_sre.SRE_Match object; span=(0, 18), match='adsfadfasdADSFAKSD'>

# ------------------------------
# 字母和数字
In [43]: pat=r'^[A-Za-z0-9]+$'

In [44]: p=re.compile(pat)
In [46]: p.search("dasfasdfsdf23141")
Out[46]: <_sre.SRE_Match object; span=(0, 16), match='dasfasdfsdf23141'>

# --------------------------------
# 整数
In [49]: pat=r'^-?\d+$'

In [50]: p=re.compile(pat)

In [51]: p.search("123")
Out[51]: <_sre.SRE_Match object; span=(0, 3), match='123'>

In [52]: p.search("+123")

In [53]: p.search("-123")
Out[53]: <_sre.SRE_Match object; span=(0, 4), match='-123'>

In [54]: p.search("-123.2")

# ------------------
# 正整数
In [56]: pat=r'^[0-9]*[1-9][0-9]*'

In [57]: p=re.compile(pat)

In [58]: p.search("31434")
Out[58]: <_sre.SRE_Match object; span=(0, 5), match='31434'>

In [59]: p.search("031434")
Out[59]: <_sre.SRE_Match object; span=(0, 6), match='031434'>

In [60]: p.search("0031434")
Out[60]: <_sre.SRE_Match object; span=(0, 7), match='0031434'>

In [61]: p.search("-31434")

# --------------------------
# 邮编
In [62]: pat=r'[1-9]\d{5}'

In [63]: p=re.compile(pat)

In [64]: p.search("314200")
Out[64]: <_sre.SRE_Match object; span=(0, 6), match='314200'>

In [65]: p.search("31420000")
Out[65]: <_sre.SRE_Match object; span=(0, 6), match='314200'>

In [66]: p.search("00031420000")
Out[66]: <_sre.SRE_Match object; span=(3, 9), match='314200'>

# ------------------------
In [68]: pat=r'[\u4e00-\u9fa5]'
# 中文字符

In [69]: p=re.compile(pat)

In [70]: p.search("把酒问青天")
Out[70]: <_sre.SRE_Match object; span=(0, 1), match='把'>

In [71]: p.findall("把酒问青天")
Out[71]: ['把', '酒', '问', '青', '天']
# ------------------------------------
# 国内电话号码
In [75]: pat=r'\d{3}-\d{8}|\d{4}-\d{7}'

In [76]: p=re.compile(pat)

In [77]: p.search("021-6891336")

In [78]: p.search("021-68913536")
Out[78]: <_sre.SRE_Match object; span=(0, 12), match='021-68913536'>

# -------------------------------------
# 匹配手机号码
import re
# pattern='\d\d\d\d\d\d\d\d\d\d\d'
pattern='1[35789]\d\d\d\d\d\d\d\d\d'
pattern='1[35789]\d{9}' # 和上面的式子 是不是等价呢? 是的。
s='13456788765'
o=re.match(pattern,s)
print(o)

#电话号码   区号-座机号  010-3762266   0342-8776262

In [12]: import re

In [13]: pattern='1[35789]\d{9}'

In [14]: s='13456788765'
    ...: o=re.match(pattern,s)

In [15]: o
Out[15]: <_sre.SRE_Match object; span=(0, 11), match='13456788765'>

在这里插入图片描述


In [2]: import re

In [3]: pat='\d+.\d+.\d+.\d+'

In [4]: p=re.compile(pat)
# 很明显
# ip 地址 没有 大于 255 的 
# 且长度 是 1 到 3
In [5]: p.findall("255.255.255.255 3333.333.333.333")
Out[5]: ['255.255.255.255 ', '3333.333.333.333']

In [14]: pat='\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}'

In [15]: p=re.compile(pat)
# 这个很明显 也是有点问题的
In [16]: p.findall("255.255.255.255 3333.333.333.333")
Out[16]: ['255.255.255.255', '3333.333.333']

在这里插入图片描述
在这里插入图片描述

In [29]: pat=r'(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{
    ...: 2}|2[0-4]\d|25[0-5])'
In [30]: p=re.compile(pat)

In [34]: p.fullmatch("255.255.255.255")
Out[34]: <_sre.SRE_Match object; span=(0, 15), match='255.255.255.255'>
# fullmatch 我个人感觉 和 match("^33.33.33.33$")  比较类似。
# 感兴趣的可以去 测试一波
In [36]: p.fullmatch("33.33.33.33") # fullmatch 全匹配
Out[36]: <_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'>

其他简单例子

# 1. 验证手机号码
text = "12567347199"
ret = re.match('1[34578]\d{9}', text)
print(ret.group())


# 2. 验证邮箱
text = "pis1@qq.com"
ret = re.match('\w+@[a-z0-9]+\.[a-z]+', text)
print(ret.group())

# 3. 验证 url 协议
text = "https://www.baidu.com/"
ret = re.match('(http|https|ftp)://[^\s]+', text)  # 竖线 就是 或的 意思
print(ret.group())

# 4. 验证身份证
text = "51152319930228159x"
ret = re.match('\d{17}[\dxX]', text)
print(ret.group())

import re
print('------案例1------')
#匹配出一个字符串首字母为大写字符,后边都是小写字符,这些小写字母可有可无
pattern='[A-Z][a-z]*'
s='Hello'
s='HEllo'
o=re.match(pattern,s)
print(o)

print('------案例2------')
#匹配出有效的变量名 (字母 、数字 下划线 ,而且数字不能开头)
# pattern='[a-zA-Z_][a-zA-Z0-9_]*'
pattern='[a-zA-Z_]\w*'
s='userName'
s='age'
s='a'
s='_qwe'
# s='3er'
o=re.match(pattern,s)
print(o)
print('-------案例3----------')
#匹配出1-99直接的数字
pattern='[1-9]\d?'
s='2'
s='99'
s='100'
s='0'
o=re.match(pattern,s)
print(o)
print('----------案例4--------------')
#匹配出一个随机密码8-20位以内  (大写字母 小写字母 下划线 数字)
pattern='\w{8,20}'
s='123456789'
s='abc123qwe_'
s='1234567#'
o=re.match(pattern,s)
print(o)

常用操作符(.,*,{},?,+,^…)

在这里插入图片描述
在这里插入图片描述

常用匹配字符串

# 重复数量符号
'''
*		:0次或多次
?		:0次或1次
+		:至少1次
{m}		:重复m次
{m,n}	:重复m到n次
{m}		:至少重复m次
{m,}    :长度的大于等于, 
{,n}    :小于等于
'''


# 常用的 匹配字符串
'''
.	匹配任意一个字符(除了\n)
[]	匹配列表中的字符
\w	匹配字母、数字、下划线,即a-z,A-Z,0-9,_
\W	匹配不是字母、数字、下划线
\s	匹配空白字符,即空格(\n,\t)
\S	匹配不是空白的字符
\d	匹配数字,即0-9
\D	匹配非数字的字符
'''

这里也有一些特殊字符的展示

比如 十六进制 Unicode\u0000:\uFFFF
ASCII\x00:\xFF

在这里插入图片描述

  • 中文字符的 Unicode 范围 \u4e00-\u9fa5

  • ascii 只能匹配 英文的。 范围为 0- 255 一共 256 个字符


关于控制字符 \cA-\cZ 对应的是 ascii1-26 的控制字符 。但是 python不支持 \cA 这种写法

所以不建议 使用 建议使用 十六进制码 或者 \t 这种写法(前提是那个字符有类似的写法)

在这里插入图片描述


演示

看完这个应该就能理解我想说的是什么了。

import re
str_="""
中国牛逼
2020-12-12
2020年12月4日19:47:07
"""
pat=r'[\n]'
pat1=r'[\x0A]'
re.findall(pat,str_)
re.findall(pat1,str_)

在这里插入图片描述


匹配某个字符串
# match, 匹配某个字符串
text = 'hello'
ret = re.match('he', text) 
# match 只会匹配前面的字符  ahello  就匹配不到了
print(ret.group())  # group 把提匹配到的字符串提取出来
. 点 , 匹配符任意的字符
# 点,匹配符任意的字符
text = 'hello'
ret = re.match('.', text)  # 但是只能匹配一个字符,但是 不能匹配换行符\n
print(ret.group())

任意字符不包括换行符

真正的任意字符可以写成 多种方式 [\w\W] [\s\S] [\d\D] 或者 使用 flags 标志 re.S


任意的数字 \d
# 任意的数字 \d   (0-9)
text = "1"
ret = re.match('\d', text)
print(ret.group())
\s 匹配空白的字符
#   \s 匹配空白的字符(例如:\n \r  \t   ,空格)
text = " a b"
ret = re.match('\s', text)
print(ret.group())
任意的非数字 \D
#  任意的非数字 \D
text = "+a"
ret = re.match('\D', text)
print(ret.group())
\w 匹配的是 a-z 和A-z 以及数字0-9和下划线
#  \w  匹配的是  a-z  和A-z   以及数字0-9和下划线
 text = "ab"
ret = re.match('\w', text)
print(ret.group())
\W 匹配 大小写字母 数字 和 下划线 以外的字符
#  \W  与 \w 相反  匹配的
 text = "+ab"
 ret = re.match('\W', text)
 print(ret.group())
*匹配多个字符
# 匹配多个字符

#   *   星号可以匹配 0个 或者任意多个 字符
text = "abdc"
ret = re.match('\d*', text)   # 这个 '\d*'  匹配任意多个数字
print(ret.group())

#    + 加号  匹配一个或者多个字符
text = "+abdc"
#  这个 '\w+'' 匹配一个以上   a-z  和A-z   以及数字0-9和下划线   组成的 字符串
ret = re.match('\w+', text)  # 因为 是从开头开始匹配  ,所以这里会报错  因为开头  匹配不到
print(ret.group())
import re
print('--------*的使用------------')
pattern='\d*'
s='123qwe'
s='123456qwe'
s='qwe'
o=re.match(pattern,s)
print(o)

? 问号 匹配一个或者0个字符
# ? 问号  匹配一个或者0个字符
text = "abdc+"

ret = re.match('\w?', text)
print(ret.group())
print('--------?的使用------------')
pattern='\d?'
s='123qwe'
s='1qwe'
s='123456qwe'
s='qwe'
o=re.match(pattern,s)
print(o)

{m}匹配m个字符
#  {m}匹配m个字符
text = "abdc+"
ret = re.match('\w{2}', text)  # 匹配两个字符
print(ret.group())



print('---------{m}-----------')
pattern='\d{2}'
pattern='\d{3}'
pattern='\d{4}'
s='123qwe'
o=re.match(pattern,s)
print(o)
{m,n} 匹配 m到n个字符
#  {m,n}匹配m到n个字符
text = "abdcdanmd;a"
ret = re.match('\w{1,5}', text)
print(ret.group())

print('---------{m,n}-----------')
pattern='\d{2,5}'
s='123qwe'
s='123456qwe'
s='qwe'
o=re.match(pattern,s)
print(o)
{m,} {,n} 实现 长度的大于等于, 小于等于
print('---------{m,}-----------')
pattern='\d{2,}'
s='123qwe'
s='123456qwe'
s='qwe'
o=re.match(pattern,s)
print(o)
# 表示 空字符串。长度为 0 的字符串。
s = ''
o1 = re.match(r'^$', s)
print(o1) # 有匹配结果,匹配到空字符串
s = '1'
print(o1) # 无匹配结果,返回 None
  • 指定开放区间,省略第2个值,保留逗号。例如 a{4, } 匹配4个或更多个连续的字符a。
脱字号 ^ 以 …开始,
# 脱字号  '^'  以 ...开始,
# 放在中括号[]里面 是取反的意思
text = "hello.py"
ret = re.search('^h\w*\.py$', text)  # match 是从开始去匹配  和 脱字号 是一样的功能
print(ret.group())
'$' 以…结尾
#  '$'   以...结尾
text = "pis1@163.com"
ret = re.match('\w+@163.com$', text)  # match 是从开始去匹配  和 脱字号 是一样的功能
print(ret.group())
'|' 匹配多个字符串或者表达式
# `'|' `   匹配多个字符串或者表达式  或者的 意思   要么 的意思
text = "http"
ret = re.match('(http|https|ftp)$', text)  # match 是从开始去匹配  和 脱字号 是一样的功能
print(ret.group())

# 匹配多个字符串
import re
pattern='aa|bb|cc'
s='aa'
o=re.match(pattern,s)
print(o)

s='bb'
o=re.match(pattern,s)
print(o)

s='my name is cc'
o=re.search(pattern,s)
o=re.match(pattern,s)
print(o)
print('匹配0-100之间所有的数字')
#匹配0-100之间所有的数字  0-99|100
pattern=r'[1-9]?\d$|100$'
s='1'
s='11'
s='99'
s='100'
s='1000'
o=re.match(pattern,s)
print(o)

关于 !^ 以及 $ 搭配使用

(^|\\s) 就代表 可以是 以 '' 就是没有字符开始 或者 \s 空白字符开始 的 字符
同理 $ 这就是 以没有"" 结尾 或者 空字符结尾

# import re
In [51]: reg
Out[51]: '(^|\\s){}(\\s|$)'

In [52]: reg2
Out[52]: '(^|\\s){}'


In [57]: re.search(reg2.format('classname'),'c classname b'
    ...: )
Out[57]: <re.Match object; span=(1, 11), match=' classname'>

In [58]: re.search(reg2.format('classname'),'classname c b'
    ...: )
Out[58]: <re.Match object; span=(0, 9), match='classname'>

In [59]: re.search(reg2.format('classname'),'a b classname'
    ...: )
Out[59]: <re.Match object; span=(3, 13), match=' classname'>

In [60]: reg2
Out[60]: '(^|\\s){}'

In [62]: reg
Out[62]: '(^|\\s){}(\\s|$)'

In [63]: re.search(reg.format('classname'),'a b classname')
    ...:
Out[63]: <re.Match object; span=(3, 13), match=' classname'>

In [64]: re.search(reg.format('classname'),'classname c b')
    ...:
Out[64]: <re.Match object; span=(0, 10), match='classname '>

In [65]: re.search(reg.format('classname'),'c classname b')
    ...:
Out[65]: <re.Match object; span=(1, 12), match=' classname '>
[ ] 组合的方式
# [ ] 组合的方式 ,只要,满足中括号 中的字符,就可以匹配
text = "a"
ret = re.match('[a1]', text)  # 匹配 a和 1
print(ret.group())
8.1
text = "0731-88888888"

#  特殊字符 需要 -前面转义  加一个\    \d是数字匹配   写一个 + 加号  就是匹配到 多个字符
ret = re.match('[\d\-]+', text)
print(ret.group())

# 8.2   中括号 代替 \d  以及 反斜杠  \w
text = "1213"
ret = re.match('[^0-9]+', text)   # 这个 ^0-9  是 匹配非0-9的字符 前面加了一个脱字号
print(ret.group())

# 8.2   中括号 代替 以及 反斜杠 \w
text = "1213"
ret = re.match('[a-zA-Z0-9_]', text)   # 这个 ^0-9  是 匹配非0-9的字符
print(ret.group())
# 8.2   中括号 代替 以及 反斜杠 \W
text = "*"
ret = re.match('[^a-zA-Z0-9_]', text)   # 这个 ^0-9  是 匹配非0-9的字符
print(ret.group())
| [ ] 两者之间的差异

# 择一匹配符 和 列表使用差异
import re
# pattern=r'[xyz]'
# s='y'
# o=re.match(pattern,s)
# print('使用列表[]:',o)
#
# pattern=r'x|y|z'
# s='y'
# o=re.match(pattern,s)
# print('择一匹配符|:',o)
# print('字符集([])和择一匹配符(|)的用法,及它们的差异')
# pattern=r'[ab][cd]'
# s='ac'
# s='ab'
# o=re.match(pattern,s)
# print(o)
# pattern=r'ab[cd]'
# # s='ab'
# # s='abc'
# s='abd'
# o=re.match(pattern,s)
# print(o)
pattern='ab|cd'
# s='abc'
# s='abd'
# s='cd'
s='ad'
s='ac'
o=re.match(pattern,s)
print(o)
+ 号 的使用
print('--------+的使用------------')
pattern='\d+'
# s='123qwe'
# s='1qwe'
# s='123456qwe'
s='qwe'
o=re.match(pattern,s)
print(o)
转义字符的使用

当然 我们也可以使用 raw 原生字符 s=r'\t123' 类似这样的语法 会经常 看到。



# 转义字符的使用
print('d:\\a\\b\\c')
print('\nabc')
print('\\nabc')
print('\t123')
print('\\t123')

import re
s='\\t123'
# pattern='\\\\t\d*'
pattern=r'\\t\d*'
o=re.match(pattern,s)
print(o)

s='\\\\t123'
# pattern='\\\\\\\\t\d*'
pattern=r'\\\\t\d*'
o=re.match(pattern,s)
print(o)
# 转义字符 和 原生字符串
text = "apple price is $299"
ret = re.search("\$\d+", text)  # 提取价格  \  转义  \$ 只想 让他作为 普通字符串
print(ret.group())


# 原生字符串
text = "\\n"  # python 中的 转义字符 把 换行符  转换成一个 普通反斜杠
text = r"\n"  # 前面加一个r  就是原生的意思  r 就是 raw   原生的意思   别的 正则里面也可以使用
print(text)


# 反斜杠    正则和 python 的 \ 反斜杠 都是 转义 ,所以 想要打印出反斜杠   需要4 个反斜杠

text = '\c'  # 这里在python 语言中  '\\n'='\n'
# python中\\\\c  => \\c
# 正则中 \\c= > \c
# ret = re.match('\\\\c', text) # 转义
ret = re.match(r'\\c', text)  # 原生字符串的方式
print(ret.group())

常用方法

常用查询,主要功能函数

在这里插入图片描述


re.search

在这里插入图片描述
在这里插入图片描述

# search 方法的使用
import re
pattern='hello'
s='hello python'
# m=re.search(pattern,s)
m=re.match(pattern,s)
print(m)
print(m.group())
print('-------macth和search的区别----------')
pattern='love'
s='I love you'
m=re.match(pattern,s)
print('使用match进行匹配',m)
o=re.search(pattern,s)
print('使用search进行匹配',o) # search 是搜索 mat是从开始位置匹配

In [26]: pattern='love'
    ...: s='I love you'
    ...: m=re.match(pattern,s)

In [27]: m

In [28]: o=re.search(pattern,s)

In [29]: o
Out[29]: <_sre.SRE_Match object; span=(2, 6), match='love'>

re.match

在这里插入图片描述

# match 方法的使用
import re
s='hello python'
pattern='hello'
o=re.match(pattern,s)
# -----------------
print(o)
print(dir(o))
print(o.group()) #返回匹配的字符串
print(o.span())
print(o.start())
# ---------------------
print('flags参数的使用')
s='hello python'
pattern='Hello'
o=re.match(pattern,s,flags=re.I)
# re.I 
# re.IGNORECASE 这两个是一样的。
# 都是忽略大小写

print(o)
print(o.group())

# -------------------
In [3]: print(o)
<_sre.SRE_Match object; span=(0, 5), match='hello'>

In [4]: print(dir(o))
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string'] # 这里是这个 match 对象的属性

In [5]: print(o.group()) #返回匹配的字符串
hello

In [6]: print(o.span()) # 匹配到的字符串的 索引范围
(0, 5)

In [7]: print(o.start()) # 匹配到的字符的 开始位置
0

In [8]: print('flags参数的使用')
flags参数的使用

In [9]: s='hello python'
   ...: pattern='Hello'
   ...: o=re.match(pattern,s,flags=re.I)
   
# re.I 
# re.IGNORECASE 这两个是一样的。
# 都是忽略大小写
In [10]:

In [10]: print(o)
<_sre.SRE_Match object; span=(0, 5), match='hello'>

In [11]: print(o.group())
hello

re.findall

在这里插入图片描述

import re
print('---------findall-------------')
s='first 1 second 2 third 3'
pattern=r'\w+'
result=re.findall(pattern,s)
print(result)

re.split

在这里插入图片描述

import re
print('----------split-------------')
s='first 11 second 22 third 33'
pattern=r'\d+'
result=re.split(pattern,s)
print(result)
result=re.split(pattern,s,maxsplit=2)
print(result)
# split   分割函数
text = "hello&world ni hao"
ret = re.split('[^a-zA-Z]', text)  # 以非英文字母为分割 符号
print(ret)

re.finditer

在这里插入图片描述

import re
print('---------finditer-------------')
s='first 1 second 2 third 3'
pattern=r'\w+'
result=re.finditer(pattern,s)
print(result)
for i in result:
    print(i.group(),end='\t')
print()

re.sub

在这里插入图片描述

import re
print('--------sub-------------')
phone='2004-959-559 # 这是一个国外电话号码'
#将phone中的注释去掉
pattern=r'#.*$'
result=re.sub(pattern,'',phone)
print('sub:',result)
pattern=r'#\D*'
result=re.sub(pattern,'',phone)
print('sub:',result)



subn

执行与相同的操作sub(),但返回一个元组 (new_string, number_of_subs_made) .

import re
phone='2004-959-559 # 这是一个国外电话号码'
#将phone中的注释去掉
pattern=r'#.*$'
print('---------subn-----------')
result=re.subn(pattern,'',phone)
print(result)
print(result[0])
print(result[1])

re.compile

在这里插入图片描述
在这里插入图片描述

import re
print('---------compile------------')
s='first123 line'
pattern=r'\w+'
regex=re.compile(pattern)
o=regex.match(s)
print(o)

# compile  函数
text = "the number is 20.50"
# 两个功能


# 功能1 正则表达  编译起来存在内存中
# r = re.compile('\d+\.?\d*')  # 用 compile 编译 保存到对象里
# ret = re.search(r, text)  # 这里直接传入对象 r 就可以了
# print(ret.group())  # 这样子 效率比较高


# 功能2 为正则写注释   这是一个好习惯     一定要写注释  方便以后 看 以及调试
r = re.compile(r"""
\d+ # 小数点前面的数
\.? # 小数点本身
\d* # 小数点后面的数字
""", re.VERBOSE)
ret = re.search(r, text)
print(ret.group())


# 查找 所有空行
'^\s(?=\r?$)\n'
rr = re.compile(r"""
^\s     # 以空白字符开头
(?=\r?$)# 回车
\n   # 换行
""", re.VERBOSE)

# re.DOTALL  匹配所有的字符

re.escape(pattern) 处理转义字符

re.escape(pattern)
在中转义特殊字符 模式 . 如果要匹配可能包含正则表达式元字符的任意文本字符串,则此选项非常有用。例如:

>>> print(re.escape('http://www.python.org'))
http://www\.python\.org

>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+

>>> operators = ['+', '-', '*', '/', '**']
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\-|\+|\*\*|\*

常用方法(函数)sub 案例

import re
# 实际的案例   替换 函数
html = '''
<dd class="job_bt">
        <h3 class="description">职位描述:</h3>
        <div class="job-detail">
        <p>岗位职责:</p>
<p>1、完成对复杂网站的数据抓取和交互模拟;</p>
<p>2、通过各种渠道或方式对相关网站进行抓取;</p>
<p>3、不断完善并维护相关网站的抓取,使之稳定运行,核心逻辑必须有单元测试;</p>
<p>4、善于灵活运用各种非爬虫技术解决爬虫相关问题;</p>
<p>5、随时响应并解决突发问题;</p>
<p>6、完成领导交办的其他工作。</p>
<p><br></p>
<p>任职要求:</p>
<p>1、本科以上学历,三年以上网站抓取经验,有电商网站、秒杀相关抓取经验;</p>
<p>2、有较强的网站分析能力,熟知各种反爬措施及相关解决办法</p>
<p>技能要求;</p>
<p>3、熟练使用eventlet、gevent、requests、selenium等技术实现高并发稳定抓取;</p>
<p>4、熟练使用消息队列(MQ)、celery等异步框架实现分布式任务处理;</p>
<p>5、熟知HTTP、TCP、Socket等底层知识;</p>
<p>6、熟练掌握Fiddler、Http debugger等抓捕工具;</p>
<p>7、熟悉MySQL、MongoDB基本使用;</p>
<p>8、熟悉Scapy,熟悉Javascript,有一定的分析能力;</p>
<p>9、能使用mock进行单元测试;</p>
<p>10、善于沟通、有团队协作精神。</p>
<p><br></p>
<p>我们的团队成员都是80后、90后,我们是充满激情和干劲的团队,我们是有梦想有追求的团队……</p>
<p>如果你有满腔热忱,如果你不想碌碌无为,如果你想通过自己的努力成为合伙人……</p>
<p>来吧!朋友,加入我们,我们会给你释放梦想的平台,我们会让你的美梦成真……</p>
<p>期待有为的你加入!!!</p>
<p>&nbsp;</p>
<p>为了让我们的小伙伴能够快乐、健康的在一起为了梦想而努力,我们提供了以下多种福利及文化活动:</p>
<p>1、每天工作8小时,弹性工作时间;</p>
<p>2、公司年度健康体检,小伙伴在为公司默默奉献的同时,公司也时刻关注着他们的健康。</p>
<p>3、量身定制的培训计划,让员工在我们细致入微的帮助下更快的融入团队。</p>
<p>4、丰富的企业文化活动:</p>
<p>Ø&nbsp; 每天:美味的零食和饮品;</p>
<p>Ø&nbsp; 每两周:组织大家去打乒乓球、羽毛球,小伙伴的健康是我们一直关注的;</p>
<p>Ø&nbsp; 每月:家人生日会(给每位寿星唱着生日快乐歌,分享美味可口的蛋糕,尽享温馨时刻);</p>
<p>Ø&nbsp; 季度:团队建设、拓展活动;</p>
<p>Ø&nbsp; 年度:大型年会(辛苦了一年的汇游科技家人,一起收获一起分享)。</p>
<p>5、每年1次调薪,两次丰厚的绩效奖金,付出与回报永远成正比哦。</p>
<p>6、节日礼品、生日礼品、结婚生子礼金等。</p>
<p>7、每天午餐补助,每月全勤奖励。</p>
<p>…………</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>汇游科技祝您面试成功!</p>
        </div>
    </dd>
'''


ret = re.sub('<.+?>', '', html)  # 非贪婪 模式  ,把 非标签的数据替换掉了
print(ret)







re匹配到的对象

比如match 或者search 匹配到 的对象 也就是 这些函数的 返回值

可以这样理解。

<_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'> 这个就是一个返回对象 。
match对象
匹配对象

返回对象的常用属性

在这里插入图片描述

返回对象的常用方法

在这里插入图片描述


贪婪模式和非贪婪模式

re 默认是贪婪模式

如何非贪婪模式?

*?, +?, ?? 这些符号 就代表非贪婪 模式 (也叫最小匹配操作符)

比如 你使用 (.*?) 匹配任意字符 但是 是非贪婪 模式 。 只匹配最少的数据。
在这里插入图片描述

# 贪婪模式 与 非贪婪模式
# 贪婪模式就是会 尽量多的 字符'\d+'
# 非贪婪模式'\d+?'  匹配到 +的   最小的 条件      # + 表示(1个或者多个匹配)
text = "0123456"
ret = re.search('\d+?', text)  # match 是从开始去匹配  和 脱字号 是一样的功能
print(ret.group())

text = "<h1>标题1</h1>"
ret = re.search('<.+?>', text)  # 非贪婪模式  问号  去掉 就是 贪婪模式
print(ret.group())
# 小案例    匹配0-101之间的数字
# 可以出现的是 1 2 3 9 100  88
# 不可以出现的是    09   101
# 有三种情况   1位1-9   2位10-99  3位  100
for text in range(1, 102):
    text1 = str(text)
    ret = re.search("^[1-9]\d?$|100$", text1)
    print(ret.group())

关于分组

(...)
匹配圆括号内的任何正则表达式,并指示组的开始和结束;组的内容可以在执行匹配后检索,稍后在字符串中与 \number 特殊顺序,如下所述。匹配文字 '('')' 使用 \(\) 或将它们括在字符类中: [(][)] .

\number
匹配同一号码组的内容。组从1开始编号。例如, (.+) \1 'the the''55 55' ,但不匹配 'thethe' (注意组后的空格)。

# (ab)	将括号中的字符作为一个分组
# \num	引用分组num匹配到的字符串

In [99]: re.match(r"(.)\1+","66555")
Out[99]: <_sre.SRE_Match object; span=(0, 2), match='66'>
# 注意这种形式 无法 匹配长度 为 1 的 字符
# 因为 这是 匹配同一 号码组的 内容。
# 进去之后先被分组了  一个数字。
# 然后和他同一号码组的 数字 就没有了
# 不信的话。 分组之后  组里面 就只有一个 数字。 可以 看看
# --------------------------------

In [100]: re.match(r"(.+)\1","thethe")

Out[100]: <_sre.SRE_Match object; span=(0, 6), match='thethe'>

In [101]: re.match(r"(.+) \1","thethe") # 这个没有输出

# 注意 组括号  和 \number 之间的空格
In [102]: re.match(r"(.+) \1","the the")

Out[102]: <_sre.SRE_Match object; span=(0, 7), match='the the'>

在这里插入图片描述


()分组 \num 别名

import re

# 示例 1 匹配座机号码  使用 ( ) 括号 分组
print('匹配座机号码')
# 匹配座机号码 区号{3,4}-电话号码{5,8}  010-43222   0432-447727
pattern=r'\d{3,4}-[1-9]\d{4,7}$'
pattern=r'(\d{3,4})-([1-9]\d{4,7}$)'
s='010-786545'
o=re.match(pattern,s)
print(o)
print(o.group())
print(o.group(1))
print(o.group(2))
# print(o.groups())
# print(o.groups()[0]) # 这样子 group() 返回的是字符串  所以这种方式 就是类似元组 切片 索引访问 字符串。
# print(o.groups()[1])

在这里插入图片描述


print('匹配出网页标签内的数据')
# 示例 2 分组示例  \num
# pattern=r'<.+><.+>.+</.+></.+>'

pattern=r'<(.+)><(.+)>.+</\2></\1>'
s='<html><head>head部分</head></html>'
# s='<html><title>head部分</head></body>'
o=re.match(pattern,s)
print(o)

在这里插入图片描述


# ( ) \1
# 正确示范,()有分组作用,正则表达式中\1可以取到分组的第一个
import re

html_str = "<h1>hahaha</h1>"
ret = re.match(r"<(\w*)>.*</\1>", html_str)
print(ret.group())

在这里插入图片描述


# ( ) \1
# 正确示范,()有分组作用,正则表达式中 \1 和 \2取值顺序
import re

html_str = "<body><h1>hahaha</h1></body>"
ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", html_str)
print(ret.group())

在这里插入图片描述


# 示例 3 分组起别名
# (?p<name>)	分别起组名
# (?p=name)	引用别名为name分组匹配到的字符串

# 示例html标签 .+ 匹配 起别名
# <(?P<k_html>.+)>

#<body><h1><div><div></div></div></h1></body>
print('(?P<name>)	分别起组名')
pattern=r'<(?P<k_html>.+)><(?P<k_head>.+)>.+</(?P=k_head)></(?P=k_html)>'
s='<html><head>head部分</head></html>'
# s='<html><title>head部分</head></body>'
o=re.match(pattern,s)
print(o)

通过观察可以发现 取了别名 就有了 groupdict

在这里插入图片描述
在这里插入图片描述



# -------------------------------

(?P<name>) 		#命名的格式 (注意P是大写的)
(?P=name)  		#取值的格式
# 
import re

html_str = "<body><h1>hahaha</h1></body>"
ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str)
print(ret.group())

在这里插入图片描述
在这里插入图片描述


import re

# 分组
text = "apple's price $99, orange's price $10"
ret = re.search('.*(\$\d+).*(\$\d+)', text)  # 将整个字符串提取出来括号里是分组的意思

print(ret.group()) # 整个正则表达式 就是一个 大的分组,可以写0或者不写  都是可以的
print(ret.group(1))  # 第一个分组
print(ret.group(2))  # 第二个分组
print(ret.group(1, 2))  # 两个分组 拿出来
print(ret.groups())  # 所有 的子分组 都拿出来

在这里插入图片描述


(...)\number

# (\number)

In [101]: a='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'
In [102]: a
Out[102]: 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'

In [103]: re.sub(r"(.)\1+",lambda x:str(len(x.group(0)))+ x.group(1),a)

Out[103]: '12WB12W3B24WB'

In [109]: re.sub(r"(.)\1+",lambda x:print(x),a)
<_sre.SRE_Match object; span=(0, 12), match='WWWWWWWWWWWW'>
<_sre.SRE_Match object; span=(13, 25), match='WWWWWWWWWWWW'>
<_sre.SRE_Match object; span=(25, 28), match='BBB'>
<_sre.SRE_Match object; span=(28, 52), match='WWWWWWWWWWWWWWWWWWWWWWWW'>
Out[109]: 'BB'

在这里插入图片描述


group 都是 从 1 开始编码

group(0) 等价于 group() 返回整个 匹配 。

groups
返回一个包含匹配的所有子组的元组,从1到模式中的所有组。这个 default 参数用于没有参与匹配的组;它默认为 None .

In [263]:  m = re.match(r"(\d+)\.(\d+)", "24.1632")

In [264]: m.groups()
Out[264]: ('24', '1632')

在这里插入图片描述


关于分组的 一些实际 例子

分组的反向引用 ( 就是那个 \1)

import re
import requests
pat="<(\w+)>(.+)<\/\1>"   # 基本套路  不过对于一些复杂的 html 标签无法 提取
res=requests.get("http://www.baidu.com")
res.encoding='utf-8'
html=res.text

pat=r"<(head)>(.+)</\1>"  # 稍加 修改
re.findall(pat,html)
# ----------------------------
# 返回结果
# [('head',
#'<meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css&gt;&lt;title&gt;百度一下,你就知道&lt;/title&gt;')]

pat=r"<(div)\s*.*?>(.+)</\1>"  # 再次修改 
re.findall(pat,html)
# 返回结果
# [('div',
#  ' <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;amp;tpl=mn&amp;amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登录</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com&gt;关于百度&lt;/a&gt; <a href=http://ir.baidu.com&gt;About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/&gt;使用百度前必读&lt;/a&gt;&amp;nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> ')]

pat=r"<(\w+)\s*.*?>(.+)</\1>" # pat="<(\w+)>(.+)<\/\1>"  完成我在一开始想用这个操作的事情。
re.findall(pat,html)
# 返回结果
#[('html',
#  ' <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css&gt;&lt;title&gt;百度一下,你就知道&lt;/title&gt;&lt;/head&gt; <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;amp;tpl=mn&amp;amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登录</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com&gt;关于百度&lt;/a&gt; <a href=http://ir.baidu.com&gt;About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/&gt;使用百度前必读&lt;/a&gt;&amp;nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> ')]

一些运行效果
在这里插入图片描述

常用的 flags

re.A

re.ASCII

制作 \w , \W , \b , \B , \d , \D , \s 和 \S 只执行ASCII匹配,而不是完全Unicode匹配。这只对Unicode 模式有意义,而对于字节模式则被忽略。对应于内联标志 (?a) .

请注意,为了向后兼容, re.U 标志仍然存在(及其同义词 re.UNICODE 及其嵌入的对应项 (?u) ,但在python 3中这些是多余的,因为字符串的匹配默认为Unicode(字节不允许使用Unicode匹配)。

re.DEBUG

显示有关已编译表达式的调试信息。没有对应的内联标志。

re.I

re.IGNORECASE

执行不区分大小写的匹配; 对应于内联标志 (?i) .

re.M

re.MULTILINE

指定时,模式字符 '^' 匹配字符串的开头每行的开头(紧跟每行换行符);以及模式字符 $ 匹配字符串的结尾和每行的结尾(紧接着每行换行符的前面)。默认情况下, '^' 仅在字符串的开头匹配,并且 '$' 只在字符串的末尾,在字符串末尾的换行符(如果有)之前。对应于内联标志 (?m) .

其实一句话 就是 换行符为边界

比如 22\n3322\n3322\n33 如果我要获取 以某某开头的两位数字字符。 以换行符为边界。 那就是 22 33 33 33


可以理解为 行首 行尾 的概念。

而不是字符串的首尾。

如果flags 用 re.M 但是想要 获取字符串首部 那就是 \A 需要写在开头 ,获取字符串尾部\Z 需要写在后面

import re
pat=r"(?m)^\d{2}"
str_="22\n3322\n3322\n33"
re.findall(pat,str_)

在这里插入图片描述

关于 \A \Z

import re
pat=r"(?m)^\A\d{2}"
str_="22\n3322\n3322\n33"
re.findall(pat,str_)
pat=r"(?m)^\d{2}\Z"
re.findall(pat,str_)

在这里插入图片描述

re.S

re.DOTALL

使'.'特殊字符完全匹配任何字符,包括换行符;如果没有此标志, '.' 会匹配任何东西 除了 换行符对应于内联标志 (?s) .


re.X

re.VERBOSE

此标志允许您编写看起来更好、更可读的正则表达式,方法是允许您直观地分隔模式的逻辑部分并添加注释


指定多个 flags 的方式

re.I | re.M | 表达符 表示 flags 被设置为了 re.Ire.M

或者使用内联的方式 (?im) 并且这个 标志要写在 最开始的位置。 否则会报 警告信息

import re
str_="""
One1
oNe2
onE3
noe4
"""
pat=r"^one\w+"
pat1=r"(?im)one\w+"
re.findall(pat,str_)
re.findall(pat1,str_)
re.findall(pat,str_,flags=re.I|re.M)
re.findall(pat,str_,flags=re.I)
re.findall(pat,str_,flags=re.M)

在这里插入图片描述

一些不常见的匹配符号

(?P=name)

  • (?P< name >)
    • 命名的格式 (注意P是大写的)
  • (?P=name)
    • 取值的格式

命名组的后向引用;它与先前命名组匹配的任何文本匹配 name .

<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>

以这为 例子

import re

html_str = "<body><h1>hahaha</h1></body>"
ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str)
print(ret.group())


(?#...)

注释;括号的内容被忽略。

相当于没写。 就可以理解为 就是 写的注释


正则 断言匹配

断言的组成之一是边界。对于文本、词或模式,边界可以用来表明它们的起始或终止部分(如向前断言,向后断言以及条件表达式)。

(?=...) => 匹配 某字符跟随某某字符 ,匹配前者。

匹配如果 ... 匹配下一个,但不使用任何字符串。这叫A lookahead assertion 前瞻性断言或者说 先行断言 . 例如, Isaac (?=Asimov) 将匹配 'Isaac ' 只有在后面跟着 'Asimov' .


向前断言:例如,对于 Jack(?=Sprat)“Jack”在跟有“Sprat”的情况下才会得到匹配./Jack(?=Sprat|Frost)/ “Jack”后跟有“Sprat”“Frost”的情况下才会得到匹配。不过, 匹配结果 不包括 “Sprat”或“Frost”

所谓的先行是指的 匹配的东西先行
条件后行。

tips: 记忆小技巧 有箭头的断言 条件都写在 前面的。
所以 都是后行。

先行断言 匹配的模式字符写在 前面
后行断言 匹配的模式字符串写在后面

断言就是指定条件。 不匹配字符。


In [81]: pat=r'Isaac (?=Asimov)'

In [82]: p=re.compile(pat)

In [85]: p.search("Isaac Asimovv") # 可以理解为 匹配 以某字符串结尾的 字符。
Out[85]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>

在这里插入图片描述


(?!...)=> 匹配 某字符串 后面没跟着某某字符。匹配前者。

匹配如果 ... 下一个不匹配。这是一个 negative lookahead assertion 否定超前断言 向前否定断言. 例如, Isaac (?!Asimov) 将匹配 'Isaac ' 只要后面不是 'Asimov' .

需要注意 ()里 这个是条件不会被匹配到的


In [69]: pat=r'Isaac (?!Asimov)'
In [74]: p.search("Isaac Asimo")
Out[74]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>
In [76]: p.search("Isaac Asimov")# 不匹配

In [77]: p.search("Isaac Asimovv")# 不匹配

In [78]: p.search("Isaac aAsimovv") # 匹配
# 可以理解为 匹配 不以 某字符串 结尾的 字符
Out[78]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>

在这里插入图片描述


(?<=...) => 匹配前面是某某字符的某字符。匹配后者

如果字符串中的当前位置前面有匹配项,则匹配 ... 当前位置结束。这叫A positive lookbehind assertion 肯定断言 或者叫做 向后肯定断言 .

(?<=abc)def 将在中找到匹配项 'abcdef' ,因为lookback将备份3个字符并检查包含的模式是否匹配。

包含的模式必须只匹配某个固定长度的字符串,这意味着 abca|b 是允许的,但是 a* 和 a{{3,4}} 不是

请注意,以正的lookbehind断言开头的模式在被搜索的字符串的开头将不匹配;您很可能希望使用 search() 函数而不是 match() 功能:

需要注意 ()里 这个是条件不会被匹配到的


import re
# 前面 有 abc 那么 我就 匹配 def 
m = re.search('(?<=abc)def', 'abcdef')
# 可以理解为以某字符串开头的 字符
m.group(0)

# 输出
'def'


# 此示例查找连字符后的单词:
# 前面有连字符 那么我就匹配后面的 这个字符
m = re.search(r'(?<=-)\w+', 'spam-egg')
m.group(0)

'egg'

在这里插入图片描述


(?<!...)=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者

如果字符串中的当前位置前面没有匹配项,则匹配 … . 这叫A negative lookbehind assertion 向后否定断言.

与正查找断言类似,包含的模式必须只匹配某些固定长度的字符串。

以负的lookbehind断言开头的模式可能在要搜索的字符串的开头匹配。

需要注意 ()里 这个是条件不会被匹配到的

In [87]:
    ...: import re
    # 前面 不是 adc 那么我就匹配后面的字符
    ...: m = re.search('(?<!abc)def', 'abcdef') # 未匹配到任何东西
In [90]:
    ...: import re
    ...: m = re.search('(?<!abc)def', 'bcdef') # 可以理解为不以某某开头的字符 后面的字符

In [91]: m.group()
Out[91]: 'def'

在这里插入图片描述

(?(id/name)yes-pattern|no-pattern)

如果给定的组 id 或 name 指向的组 有值 将尝试 使用 yes-pattern 匹配一些字符 ,否则尝试使用 no-pattern 匹配一些字符 。 no-pattern 是可选的,可以省略。


特殊序列包括 '\' 以及下面列表中的一个字符。如果普通字符不是一个ASCII数字或一个ASCII字母,那么得到的RE将与第二个字符匹配。例如, \$ '$'匹配 .


在这里插入图片描述

相信 看完 这几张图 然后 自己实验 一下 所有人都能理解这是什么意思。

  • pat="(\w+@\w+(?:\.\w+)+)"
  • pat="(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|>$)"
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • s1 的分组 id1 的 匹配了 < 说明有值 那么match=<user@host.com 使用 yes 模式 尝试匹配> 因为 s1user@host.com 所以匹配成功
  • s3的分组id1 的 组 值为None 所以使用 no 模式 。然后 s3=user@host.com> 所以no 模式我写的 匹配 > 也匹配到了。

在这里插入图片描述


常用正则速查

/这里是正则/

js 中正则就是 写在 // 下划线中的

示例(比如我要验证用户名)

import re
pat='^[a-z0-9_-]{3,16}$'
str="你要验证的字符串"
re.match(pat,str)

如果已有的正则 不符合你的 要求

记得自己修改一下哦


用户名/^[a-z0-9_-]{3,16}$/
密码/^[a-z0-9_-]{6,18}$/
十六进制值/^#?([a-f0-9]{6}|[a-f0-9]{3})$/
电子邮箱/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/
URL/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
IP 地址/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 标签/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/
删除代码\\注释(?<!http:|\S)//.*$
Unicode编码中的汉字范围/^[\u2E80-\u9FFF]+$/
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值