intellij idea安装 设计模式 ASP.NET Core 阿里巴巴 iic ssl datepicker Normalizecss vue使用教程 vue遍历 多店版微信商城 jquery第一个子元素 jquery选择器找子元素 mac安装hadoop java数据分析 etc文件夹 新手学c还是java mysql或者条件 wps文件修复工具下载 python练习 pythonsocket编程 python3入门 python获取数据类型 python编程教程 python查找指定字符 java中的多态 java数组添加值 java路径 java定义 php语言入门 ad19 mac画图软件 考试练习系统 迅雷去广告版 collect 谷歌地球用不了 c语言编程实例 小票打印 批量插入数据 游戏linux正则表达式
当前位置: 首页 > 学习教程  > python

【1.1正则表达式】Python核心编程(第三版)猴子都能看懂的笔记

2021/2/8 12:16:05 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

文章目录正则表达式起始和结尾部分指定单词边界匹配限定范围和否定正则常用符号使用圆括号指定分组扩展表示法扩展表示法1.3正则表达式和Python语言常见的正则表达式属性1.3.4使用match()方法匹配字符串择一匹配的范围更局限1.3.9 重复、特殊字符以及分组1.3.10 匹配字符串的起…

文章目录

  • 正则表达式
  • 起始和结尾部分指定
    • 单词边界匹配
    • 限定范围和否定
    • 正则常用符号
    • 使用圆括号指定分组扩展表示法
    • 扩展表示法
  • 1.3正则表达式和Python语言
    • 常见的正则表达式属性
    • 1.3.4使用match()方法匹配字符串
    • 择一匹配的范围更局限
    • 1.3.9 重复、特殊字符以及分组
    • 1.3.10 匹配字符串的起始和结尾以及单词边界
  • 1.3.11 使用findall()和finditer()查找每一次出现的位置
    • re模块函数:常见的正则表达式属性
    • 使用sub()和subn()搜索与替换
    • 在限定模式上使用split()分隔字符串
  • 扩展符号
    • re.M/re.MULTILINE实现多行混合
    • re.S/re.DOTALL使点号能够用来表示\n符号
    • re.X/VERBOSE
    • (?:…)对正则表达式进行分组
    • (?P< name >)
      • ` \g`
      • (?x)
    • 字符串格式化符号
    • 正向前视断言(?…) 负向前视断言 (?!…)
    • 使用条件正则表达式匹配
  • 一些正则表达式示例
    • 示例1-1 分割windows的tasklist命令 file对象
    • 示例1-2 分割windows的tasklist命令 with语句
    • 示例1-3 分割windows的tasklist命令 printf语句(2、3通用)
    • 示例1-4 处理DOS环境下tasklist命令的输出
  • 更长的正则表达式示例
    • 示例1-5 用于正则表达式练习的数据生成器
    • 匹配字符串
    • 分组 ^()
    • 搜索、匹配与贪婪

辅助阅读:

  • https://blog.csdn.net/hehe_win/article/details/54602584
  • 注意!CSDN与实际MD文档显示有格式差异,有些代码会在代码块外部
  • 基于《笨办法学习Python3》

正则表达式

择一匹配匹配的字符串
bat|bet|bitbat、bet、bit
匹配 句点位置匹配的字符串
f.o
.end
任意 两字符

转义字符:‘\’

search():搜索——任何位置开始匹配

match():匹配——起始字符开始匹配

搜索 起始和结尾部分指定:"\A 或 ^"

匹配 字符串的末尾位置:"$ 或 \Z"

美元符号:.*\$$

注意:书中目前没说\A和\Z用法

起始和结尾部分指定

起始和结尾部分指定匹配的字符串
^From
/bin/tcsh$
起始字符…【行首】
…结尾字符
^Subject:hi$单独字符串
img img

单词边界:在匹配时会忽略换行和特殊字符

例如:James 1abc,正则\Babc,结果找到

单词边界匹配

单词边界匹配匹配的字符串
the任何包含
\bthe起始字符**【单词边界】**
\bthe\b仅匹配单词**【会忽略特殊字符】**
\Bthe不以the开头

限定范围和否定

限定范围和否定
b[aeiu]t
[cr][23][dp][o2]
匹配方括号中包含的任何单字符**【字符集】**
Z.[0-9]
[A-Za-z][env-y]
小数**【指定字符范围】**
[^ASD]不匹配的 单字符
[^\t\n]不匹配的 制表符
["-a]ASCII系统,所有系统位于""和"a"之间,即34-97之间

正则表达式[ab],'a’和’b’是相互独立,但只能匹配单字符

否则用a|b

使用闭包操作符实现存在性和频数匹配。。。
[dn]ot?0~1次出现
0?[1-9]01~09月
[0-9]{15,16}匹配15~16次**【信用卡号码】**
</?[^>]+>匹配全部HTML标签**【不验证有效性】**
[KQRBNP][a-h][1-8][a-h][1-8]~~在“长代数”标记法中,表示国际象棋合法的棋盘移动(仅移动,不包括吃子和将军)。即K、Q、R、B、N、P等字母后加上a1h8之间棋盘坐标。坐标1从哪走,坐标2走到哪个位置~

\*匹配星号

多次使用问号:问号在任何使用闭合操作符的匹配后面,它将直接要求正则表达式引擎匹配尽可能少的次数+

正则常用符号

Name匹配前面正则
(*)0+ 【Kleene闭包】
(+)1+ 【正闭包操作符】
(?)0~1
[Mr?]:Mr或M
{M,N}
{M}
匹配 前面正则 M~N次
表示字符集的特殊字符
\d十进制数字
\D非十进制数
[^0-9]
\w全部字母数字
[A-Za-z0-9_]
\s空白字符
\w+-\d+		#字母数字-数字
'''减号只在字节集下有效'''
#a1-1
#2a-2

[A-Za-z]\w*			#首字符是任意字母大小写,其余是字母或数字,可有可无
\d{3}-\d{3}-\d{4}	#美国号码:800-555-1212
\w+@\w+\.com		#简单电子邮件地址

使用圆括号指定分组扩展表示法

可用闭包操作符 独立执行部分“()“

\d+(\.\d*)?			#浮点数,会保留句点
(Mr?s?\.)?[A-Z][a-z]*[A-Za-z-]+		#M.Co-co

【称谓可有可无】,【首字母大写】,【小写字母可有可无】,【字母、大小写或”-“】一次以上

扩展表示法

圆括号有一个副作用:匹配模式的子字符串可以保存起来供后续使用。这些子组能够被同一次的匹配或者搜索重复调用,或者提取出来用于后续处理。

示例:1.3.9

“()”使自己相关的匹配被缓存,?:放在第一个选项前来抵消这种副作用

但这些匹配不会保存下来供后须使用和数据检索

参考:python re 扩展表示法

(?iLmsux)在正则表达式中嵌入一个或者多个特殊"标记"参数(?x),(?im)

(?:…)表示一个匹配不用保存的分组(?:\w+.)*

(?P<name>...)像一个仅由name标示而不是数字ID标示的正则分组匹配(?P<data>)

(?P=name)在同一个字符串中匹配由(?P<name)分组的之前文本(?P=data)

(?#…)标示注释,所有内容都被忽略(?#comment)

(?=…)匹配条件是如果…出现在之后的位置,而不适用输入字符串;称作正向前视断言(?=.com)

(?!..)匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言(?!.net)

(?<=…)匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言(?<=800-)

(?<!..)匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言(?<!192.168.)

(?(id/name)Y|N)如果分组所提供的id或者name存在,就返回正则表达式的条件匹配Y,如果不存在,就返回N;|N是可选项。(?(1)y|X)

(?:\w+\.)*			#表示一个匹配不用保存的分组
(?#comment)			#注释
(?=.com)			#任意字符.com
(?!.net)			#字符不是跟着.net
(?<=800-)			#字符头部为“800-”才匹配
(?<!192\.168\.)		#字符之前不是192.168.才做匹配 【过滤C类IP地址】
(?(l)y|x)			#???

1.3正则表达式和Python语言

常见的正则表达式属性

函数/方法描述
仅仅是re模块函数
compile(pattern,flags=0)使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象
re 模块的函数和正则表达式对象的方法
match(pattern,string, flags=0)尝试使用带有可选的标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象;如果失败,就返回None
search(pattern,string, flags=0)尝试可选标记搜索字符串中第一次出现的正则表达式模式。如果匹配成功,就返回匹配对象;如果失败,就返回None
findall(pattern,string[,flags])查看字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表
finditer(pattern,string[, flags])与findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭代器都返回一个匹配对象
split(pattern,string, max=0)根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表,分割最多操作max次(默认分割所有匹配成功的位置)
sub(pattern, repl, string, max=0)使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义count,否则就将替换所有出现的位置
purge()消除隐式编译的正则表达式模式
常见的匹配方法
group(num=0)返回整个匹配对象,或者编号为num的特定子组
groups(default=None)返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回一个空元组)
groupdict(default=None)返回一个包含所有匹配的命名子组的字典,所有的子组名称作为字典的键(如果没有成功匹配,则返回一个空字典)
常用的模块属性
re.I、re.IGNORECASE不区分大小写的匹配
re.L、re.LOCALE根据所使用的本地语言环境通过\w、\W、\b、\B、\s、\S实现匹配
re.M、re.MULTILINE^和$分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾
re.S、re.DOTALL“.”(点号)通常匹配除了\n(换行符)之外的所有单个字符;该标记表示“.”(点号)能够匹配全部字符
re.X、re.VERBOSE通过反斜线转义,否则所有空格加上#都被忽略,除非在一个字符类中或者允许注释并且提高可读性

1.3.4使用match()方法匹配字符串

match()函数从起始位置匹配,匹配成功:返回对象,否则None

re.match('(ab)', 'ab')
m.group(1)           # 子组 1

group()返回值:整个匹配对象、‘特定要求子组。

groups()返回值:包含1个以上子组的元组。

若无子组group()返回完整匹配,groups() 返回空元组“()”

re.match('ab', 'ab').group()		# 没有子组
'ab'								# 完整匹配
m.groups()           				# 所有子组
()
import re

bt = 'bat|bet|bit'
re.match(bt,'batL').group()						#'bat'
re.search(bt, 'He bit me!') .group()			#'bit'
# 起始位置【匹配】
# 任意位置【搜索】
# 判断避免AttributeError异常,group()无法处理None



m = re.search('.end', 'The end.')
if m is not None:print(m.group())		# “ end”

re.match('3\.14', '3.14').group()		# 3.14
'''
(.)句点叫空字符可以替换小数点,不能匹配 换行符 或者 非字符 ,不包括空格
'''

"模式"叫“pattern”——匹配的正则表达式,书中叫法特

择一匹配的范围更局限

re.match('[cr][23][dp][o2]', 'c2do')
re.match('r2d2|c3po', 'c2do')		# 不匹配 'c2do'

1.3.9 重复、特殊字符以及分组

re.match('(ab)', 'ab').groups()		# ('ab',)


m = re.match('(a)(b)', 'ab')
m.group()							# 'ab' ——整个匹配对象
m.group(2)							# b
m.groups()							# ('a', 'b')


m = re.match('(a(b))', 'ab')		
m.groups()							# ('ab', 'b')

group() 返回整个匹配对象、要求的特定子组。

groups() 返回包含全部或唯一子组的元组、无匹配返回空元组

import re
单次子域名 = '\w+@(\w\.)?\w\.com'
多次子域名 = '\w+@(\w+\.)*\w+\.com'
特殊地址 = '(\w+)-(\d+)'
#nobody@www.xxx.com
#nobody@xxx.com
#nobody@www.xxx.yyy.zzz.com

1.3.10 匹配字符串的起始和结尾以及单词边界

search()和match()用法完全一致,当前进度group()都没数据

re.search('^The', 'The end.').group()		#'The'

m = re.search('^The', 'end.The')			# 不作为起始
if m is not None: m.group()
...
#任何以The为起始的字符串
re.search('^The', 'The end.').group()
#同match()从起始位置进行匹配
#re.search('^The', 'end.The').group()	#None	

# 起始字符【单词边界】
re.search(r'\bthe', 'bite the dog').group()

# 包含 但不以the起始
re.search(r'\Bthe', 'bitethe dog').group()

不懂什么是有边界和无边界,但能理解命令,见:《起始和结尾部分指定》

1.3.11 使用findall()和finditer()查找每一次出现的位置

re模块函数:常见的正则表达式属性

函数/方法描述
仅仅是re模块函数
compile(pattern,flags=0)使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象
re 模块的函数和正则表达式对象的方法
match(pattern,string, flags=0)尝试使用带有可选的标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象;如果失败,就返回None
search(pattern,string, flags=0)尝试可选标记搜索字符串中第一次出现的正则表达式模式。如果匹配成功,就返回匹配对象;如果失败,就返回None
findall(pattern,string[,flags])查看字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表
finditer(pattern,string[, flags])与findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭代器都返回一个匹配对象
split(pattern,string, max=0)根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表,分割最多操作max次(默认分割所有匹配成功的位置)
sub(pattern, repl, string, max=0)使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义count,否则就将替换所有出现的位置
purge()消除隐式编译的正则表达式模式
常见的匹配方法
group(num=0)返回整个匹配对象,或者编号为num的特定子组
groups(default=None)返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回一个空元组)
groupdict(default=None)返回一个包含所有匹配的命名子组的字典,所有的子组名称作为字典的键(如果没有成功匹配,则返回一个空字典)
常用的模块属性
re.I、re.IGNORECASE使匹配对大小写不敏感
re.L、re.LOCALE根据所使用的本地语言环境通过\w、\W、\b、\B、\s、\S实现匹配
re.M、re.MULTILINE==【多行匹配】==影响 ^ 和 < b r / > 和 <br />^和 <br/>分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾
re.S、re.DOTALL==【单行模式】==使 “.”(点号)匹配包括换行在内的所有字符
re.X、re.VERBOSE通过反斜线转义,否则所有空格加上#都被忽略,除非在一个字符类中或者允许注释并且提高可读性

注意: match 和 search 是匹配一次 findall 匹配所有。

帮助地址:Finadall和Finditer区别

findall(string[, pos[, endpos]])

  • string 待匹配的字符串。
  • pos 可选参数,指定字符串的起始位置,默认为 0。
  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

findall(pattern,string[,flags]) 【匹配列表】查看字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表

[‘car’, ‘car’, ‘car’]

finditer(pattern,string[, flags]) 【迭代器】与findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭代器都返回一个匹配对象

[(‘This’, ‘that’)] #要求多个字组

>>> re.findall('car', 'carry the barcardi to the car')
['car', 'car', 'car']

re模块的*finditer()函数报出AttributeError*: ‘callable_iterator’ object has no attribute ‘next’*的错误:

https://blog.csdn.net/weixin_43148062/article/details/105639146+

#当前版本【3.9】
>>> it = re.finditer(r'(th\w+) and (th\w+)',s,re.I)
>>> next(it).groups()
('This',)

#书中写法【过时】
>>> it.next().groups()
('This',)

别管为啥有个逗号,他只有一个元素

\w会在空字符作为边界

re.I(不区分大小写)

import re
s = 'This and that.'
res = re.finditer(r'(th\w+) and (th\w+)',s,re.I)
print(next(res).group(2))
#print(next(res).groups())
#只能执行一个

============================================
that
('This', 'that')

next()不仅会返回下一行,猜测是同概念,但指向不同东西,不明白为啥加next()

#下面子字符位置,0是起始位置
>>> print(next(it))
<re.Match object; span=(0, 4), match='This'>
import re
s = 'This and that.'


'''多个子组'''
re.findall(r'(th\w+) and (th\w+)', s, re.I)		#[('This', 'that')]
re.findall(r'(th\w+)', s, re.I)					#['This', 'that']
import re
s = 'This and that.'							#r原样输出

res = re.finditer(r'(th\w+) and (th\w+)',s,re.I)
g = next(res)
g.groups()								#('This', 'that')
#全部子组

res = re.finditer(r'(th\w+) and (th\w+)',s,re.I)
g = next(res)
g.group(2)								#'that'
#子组2

[g.group(1) for g in re.finditer(r'(th\w+)', s, re.I)]
#['This', 'that']

使用sub()和subn()搜索与替换

  • re.sub(‘查找’, ‘替换为’, ‘字符串’) 实现搜索与替换功能,返回一个用来替换的字符串。

  • subn(‘查找’, ‘替换为’, ‘字符串’) 实现搜索与替换功能,返回元组:替换后字符、替换总数

>>> import re
>>> 
>>> re.sub('查找、正则', '替换为', '字符串')
'处理结果'
>>> re.subn('查找', '替换为', '字符串')
('处理结果', 总数)

>>>
re.sub('[ae]', '+', 'abcdef')
'+bcd+f'
>>> re.subn('[ae]', '+', 'abcdef')
('+bcd+f', 2)

>>> print (re.sub('X', 'Mr.Smith', 'attn: X\n\nDear X,\n'))
attn: Mr.Smith
Dear Mr.Smith,


#匹配两次1或2位数字,匹配2或4位数字
>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3','2/20/91')
'20/2/91'
>>> re.sub(r'同上','同上','2/20/1991')
'20/2/1991'

发现一个意料之外:无关不帮助理解

>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3','33777777777744/20/1991')
'33777777777720/44/1991'

在限定模式上使用split()分隔字符串

文本.split(str="", num=string.count(str)).

split(pattern,string, max=0)

根据split分割文本,返回成功匹配列表,分割最多操作max次。(默认无上限)

split可以代替复杂且影响性能的正则表达式。

>>> import re
>>> DATA=(
     'Mountain View,VA94040',
     'Sunnyvale, VA',
     'Los Altos, 94023',
     'Cupertino 95014',
     'Palo Alto CA',
 )
>>> for datum in DATA:
     print re.split(', |(?= (?:\d{5}|[A-Z]{2})) ',datum)

'''任意字符(不保存分组,数字5位或 任意两个大写字母)'''
""" 
'逗号'在print打印时就没有了,因为在字符串外,所以for基于逗号进行了逐个取出
正则中逗号代表
"""
        
        
        
#(?:...)表示一个匹配不用保存的分组(?:\w+\.)*
#例如:?=.com,任意字符.com
=========================================
['Mountain View', 'VA', '94040']
['Sunnyvale', 'VA']
['Los Altos', '94023']
['Cupertino', '95014']
['Palo Alto', 'CA']

扩展符号

re.M/re.MULTILINE实现多行混合

见:《re模块函数:常见的正则表达式属性》

参考:

【推荐】Python正则表达式中的re.S,re.M,re.I的作用

re.S 和 re.M的一点区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwW1vA9i-1612699840524)(Python核心编程(第三版).assets/image-20210130173242877.png)]

为了更好的理解,只退进书中进度,上面反斜杠和单引有错

  • re.m(?m):跨行搜索,不必将整个字符串视为单个实体

  • re.i(?i):不区分大小写

#不区分大小写
>>> re.findall(r'(?i)yes','yes? yesYes. YES!!')
['yes', 'yes', 'Yes', 'YES']



import re


#部分大小写,多行匹配
s =re.findall(r'(?im)(^th[\w ]+)', """
This line is the first,
another line,
that line,
it's the best
""")

print(s)

================================================


['This line is the first', 'that line']

re.S/re.DOTALL使点号能够用来表示\n符号

res.s:==【单行模式】==使 “.”(点号)匹配包括换行在内的所有字符

>>> re.findall(r'th.+','''
The first line
the second line
the third line
''')
['the second line', 'the third line']

>>> re.findall(r'(?s)th.+', '''
The first line
the second line
the third line
''')
['the second line\nthe third line\n']

re.X/VERBOSE

换一种说法解释:这个选项忽略规则表达式中的空白和注释,并允许使用 ’#’ 来引导一个注释。这样可以让你把规则写得更美观些。

(书里写的真是拐弯抹角)

re.search(r'''(?x)
     \((\d{3})\)  #区号
     [ ]          #空白符
     (\d{3})      #前缀
     -            #横线
     (\d{4})      #终点数字
 ''','(800) 555-1212').groups()

#如果还在懵圈请把正则和被匹配的空格去掉,这会干扰理解
#另外我常省略

(?:…)对正则表达式进行分组

使用圆括号会被缓存,使用(?:…)不会缓存,只用来匹配正确性

帮助:【推荐】Python正则表达式之 - ?: / ?= / ?!

Python 正则表达式(分组)

正则表达式(四):正则表达式中的分组的概念

>>> re.findall(r'http://(?:\w+\.)*(\w+\.com)','http://google.com http://www.google.com http://code.google.com')
['google.com', 'google.com', 'google.com']

不加?:

  • 如果有多层子域名,只会输出最后一个aaa.
>>> re.findall(r'http://(\w+\.)*(\w+\.com)','http://google.com http://www.google.com http://code.google.com http://www.code.aaa.google.com')

==================================================
[('', 'google.com'), ('www.', 'google.com'), ('code.', 'google.com'), ('aaa.', 'google.com')]

在线工具中与实际输出不同:https://tool.oschina.net/regex#

image-20210131163458458

(?P< name >)

返回:根据?p<name>的name为字典键名

>>> re.search(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})','(800) 555-1212').groupdict()
{'areacode': '800', 'prefix': '555'}

\g<name>

参考:re模块中 (?P<name>) (?P=name)\g<name> 三者的使用区别

可以使用(?P<name>)创建元组,然后用(\g<name>)复用这个匹配

import re

astr = 'aabb aacc aadd'
result = re.sub(r'(?i)aa(?P<pattern>[\w]+)',r'bb\g<pattern>',astr)
print('{} _____ {}'.format(astr,result))

re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})','(\g<areacode>) \g<prefix>-xxxx', '(800) 555-1212')

#上面书里没有的命令一看就会吧
=================================
aabb aacc aadd _____ bbbb bbcc bbdd

(?x)

  • (?x):空格必须用[ ]代替,否则执行结果不同
  • 参考地址:正则表达式中 ?=.* 是什么含义? - 知乎用户的回答 - 知乎
  • ?p=<name>返回布尔值
import re

s = bool(re.match(r'''(?x)\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?P<number>\d{4}) (?P=areacode)-(?P=prefix)-(?P=number) 1(?P=areacode)(?P=prefix)(?P=number)''','(800) 555-1212 800-555-1212 18005551212'))


z = bool(re.match(r'''(?x)
    \((?P<areacode>\d{3})\)[ ](?P<prefix>\d{3})-(?P<number>\d{4})
     [ ]
     (?P=areacode)-(?P=prefix)-(?P=number)
     [ ]
      1(?P=areacode)(?P=prefix)(?P=number)
 ''', '(800) 555-1212 800-555-1212 18005551212'))

print(s)

print('\n',z)
===================================================
False

 True

字符串格式化符号

image-20210201175023157
  • 参考地址:https://jingyan.baidu.com/article/454316abaf775ab6a6c03a7b.html
>>> '%c 打印一个字母'  % (97)
'a 打印一个字母'
>>> '单推%s 娘'  % '22'
'22 娘'

正向前视断言(?…) 负向前视断言 (?!…)

  • 参考:https://blog.csdn.net/csm0912/article/details/81206848

    https://zhidao.baidu.com/question/1110915947964324019.html

  • 断言正则成立,则运行子组正则

// 正向前视断言	【要求之内】
exp1(?=exp2) 	//exp2前面是exp1
(?<=exp2)exp1 	//exp2后面是exp1


// 负向前视断言	【要求之外】
exp1(?!exp2) 	//exp1后面不是exp2
(?<!exp2)exp1 	//exp1前面不是exp2
re.findall(r'\w+(?= van Rossum)',
'''
   Guido van Rossum
   Tim Peters
   Alex Martelli
   Just van Rossum
   Raymond Hettinger
''')

==============================================
['Guido', 'Just']
  • ?m【多行匹配】不需要像?x那样使用[ ]来充当空格,而是原始文本输出

  • \s用于匹配空白字符。所以正则:以空白字符开头的字符

  • 字符边界(重复):一 二 三 ,就跟编辑器Ctrl+D一样

    image-20210202145752310
import re

#?m【多行匹配】
#\s【空字符】
z = re.findall(r'(?m)^\s+(?!noreply|postmaster)(\w+)',
'''
   sales@phptr.com
   postmaster@phptr.com
   eng@phptr.com
   noreply@phptr.com
   admin@phptr.com
''')


print('\n',z)


============================================
['sales', 'eng', 'admin']
  • 请参考《字符串格式化符号》,这就类似于f'{}{}'.format('1','2') 输出:‘12’
import re

z = ['%s@aw.com' % e.group(1) for e in \
re.finditer(r'(?m)^\s+(?!noreply|postmaster)(\w+)',
'''
   sales@phptr.com
   postmaster@phptr.com
   eng@phptr.com
   noreply@phptr.com
   admin@phptr.com
''')]

print('\n',z)
=================================================
 ['sales@aw.com', 'eng@aw.com', 'admin@aw.com']

使用条件正则表达式匹配

  • ?(1)参考链接,我看不太懂,貌似和布尔值有关

bool()类型判断::https://blog.csdn.net/u014472777/article/details/90318960

print(bool(re.search(r'(?:(x)|y)(?(1)y|x)','xy')))		#True
print(bool(re.search(r'(?:(x)|y)(?(1)y|x)','yx')))		#True
print(bool(re.search(r'(?:(x)|y)(?(1)y|x)','x')))		#False
#使用条件正则表达式。上述匹配一个字符串:两个字母必须由一个字母跟着另一个字母,两个字母不能相同
使用python原始字符串

退格符\b和正则表达式\b之间的差异

\w和\W字母数字字符集同时受re.L/LOCALEUnicode(re.U/UNICODE)标记所影响。

书里很多是啰嗦。

  • '\b' = 退格符
  • '\\b' = \b
  • r'\b' = 单词边界

\d 使用原始字符串时并未遇到问题,这是因为ASCII中没有相应的特殊字符

>>> m=re.match('\bblow','blow')
>>> if m:    m.group()
...
>>> m=re.match('\\bblow','blow')
>>> if m:    m.group()
...
'blow'
>>> m=re.match(r'\bblow','blow')
>>> if m:    m.group()
...
'blow'

一些正则表达式示例

  • 为啥实例化文本才会按行读取,直接赋值多行不可以
  • r'字符串' 用于避免转义特殊字符串字符,如\n,可以用\\s 代表\s
System Idle Process              0 Services                   0          4 K
System                           4 Services                   0      9,212 K
smss.exe                       464 Services                   0        544 K
csrss.exe                      708 Services                   0      2,792 K
wininit.exe                    816 Services                   0      2,808 K
services.exe                   888 Services                   0      5,220 K
lsass.exe                      904 Services                   0     10,984 K
re.split(r'正则匹配分隔文本', 字符串)
import re

for i in open('whodata.txt', 'r'):
    print(re.split(r'\s\s+',i))
#坏习惯↑
===================================================
['System Idle Process', '0 Services', '0', '4 K\n']
['System', '4 Services', '0', '9,212 K\n']
['smss.exe', '464 Services', '0', '544 K\n']
['csrss.exe', '708 Services', '0', '2,792 K\n']
['wininit.exe', '816 Services', '0', '2,808 K\n']
['services.exe', '888 Services', '0', '5,220 K\n']
['lsass.exe', '904 Services', '0', '10,984 K\n']

示例1-1 分割windows的tasklist命令 file对象

  • 去除尾部的\n(使用 str.rstrip())

Python2**(Python3见示例1-2)**

使用str.rstrip()去除尾部的\n

import os
import re
f = os.popen('tasklist', 'r')
for eachLine in f:
    print re.split(r'\s\s+|\t', eachLine.rstrip()) #使用str.rstrip()去除尾部的\n
f.close()


=======================================================
部分python结果展示:
['\xd3\xb3\xcf\xf1\xc3\xfb\xb3\xc6', 'PID \xbb\xe1\xbb\xb0\xc3\xfb', '\xbb\xe1\xbb\xb0#', '\xc4\xda\xb4\xe6\xca\xb9\xd3\xc3']
['========================= ======== ================ =========== ============']
['System Idle Process', '0 Services', '0', '4 K']
['System', '4 Services', '0', '9,212 K']
['smss.exe', '464 Services', '0', '544 K']
['csrss.exe', '708 Services', '0', '2,796 K']
['wininit.exe', '816 Services', '0', '2,808 K']
['services.exe', '888 Services', '0', '5,220 K']
['lsass.exe', '904 Services', '0', '10,968 K']

示例1-2 分割windows的tasklist命令 with语句

  • Python3.9多行超长输出:他是程序内部运行的Shell命令,简单理解是遍历目录

with语句兼容性(最低支持2.6)

  • 2.5为试验性的,2.5需要导入额外的语句

    from __future__ import with_statement。
    
  • 2.4或更低:

    只能用示例1-1了

https://www.zhihu.com/question/50979825/answer/124024569

调用其他程序,需要调用os.popen()

tasklist 是个程序名,返回一个文件列表

import os
from distutils.log import warn as printf
import re
with os.popen('tasklist', 'r') as f:
    for eachLine in f:
        printf(re.split(r'\s\s+|\t', eachLine.rstrip()))
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()

不管程序是否出错,finally以下的代码都是不受影响的,都可以正常运行。

上面太冗长了,with可以简化他了。别问我TRY是啥,太跨越了

打开文件参数,路径一般都是相对路径。as命令参数赋值file

with open("/tmp/foo.txt") as file:
data = file.read()

参考地址:上面只是摘选

python中finally的作用

python中 with-as 语句用法

示例1-3 分割windows的tasklist命令 printf语句(2、3通用)

import os
from distutils.log import warn as printf
import re

with os.popen('tasklist', 'r') as f:
    for eachLine in f:
        printf(re.split(r'\s\s+|\t', eachLine.rstrip()))
部分python结果展示:
['\xd3\xb3\xcf\xf1\xc3\xfb\xb3\xc6', 'PID \xbb\xe1\xbb\xb0\xc3\xfb', '\xbb\xe1\xbb\xb0#', '\xc4\xda\xb4\xe6\xca\xb9\xd3\xc3']
['========================= ======== ================ =========== ============']
['System Idle Process', '0 Services', '0', '4 K']
['System', '4 Services', '0', '9,212 K']
['smss.exe', '464 Services', '0', '544 K']
['csrss.exe', '708 Services', '0', '2,796 K']
['wininit.exe', '816 Services', '0', '2,808 K']
['services.exe', '888 Services', '0', '5,220 K']
['lsass.exe', '904 Services', '0', '10,968 K']

示例1-4 处理DOS环境下tasklist命令的输出

import os
import re
f = os.popen('tasklist /nh', 'r')
for eachLine in f:
    print re.findall(r'([\w.]+(?: [\w.]+)*)\s\s+(\d+) \w+\s\s+\d+\s\s+([\d,]+ K)', eachLine.rstrip())
f.close()

Python3.9:

image-20210206184728561

cmd:tasklist /nh

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GhsGlot2-1612699840549)(Python核心编程(第三版).assets/image-20210206184912309.png)]

更长的正则表达式示例

示例1-5 用于正则表达式练习的数据生成器

该脚本为正则表达式练习创建随机数据,然后将生成的数据输出到屏幕。

参考
https://www.runoob.com/python/func-number-randrange.html
https://blog.csdn.net/qq_37369726/article/details/108769380

from random import randrange, choice

randrange():要求范围内随机数

random.randrange (1,3 ) :取随机数(小~大),最大值必填
random.choice(list):随机取列表成员

from string import ascii_lowercase as lc

所有的小写字母

from sys import maxint

返回系统最大整数。

from time import ctime

时间戳,返回一段自1970.1.1 8:00开始的秒数(格林威治午夜)

Sun Sep 7 17:29:09 2008

from sys import maxsize
print(ctime(randrange(maxsize)))
=====================================
Sun Feb 26 01:11:48 2023

增量:

for temp in xrange(0,6):

快速创建有1~5整数列表,能限制for循环次数

序列也叫列表

image-20210206210353141
  • 适配Python3
    • 修改Python,
    • xrange()修改为range(),
    • 将sys.maxint修改为sys.maxsize。
#Python3

from random import randrange, choice
from string import ascii_lowercase as lc # 全部小写字母集成	`为列表
from sys import maxint
from time import ctime

tlds = ('com', 'edu', 'net', 'org', 'gov')  # 高级域名集合

for i in xrange(randrange(5, 11)):
    dtint = randrange(maxint)  # 随机生成一个整数
    dtstr = ctime(dtint)       # 使用time.ctime()函数将该整数转换为日期
    llen = randrange(4, 8)     # login is shorter
    login = ''.join(choice(lc) for j in range(llen)) # random.choice()函数的功能是接受一个序列,然后返回该序列的一个随机元素
    dlen = randrange(llen, 13)  # domain is longer
    dom = ''.join(choice(lc) for j in xrange(dlen))
    print '%s::%s@%s.%s::%d-%d-%d' % (dtstr, login, dom, choice(tlds), dtint, llen, dlen)

输出结果:

image-20210206220139085

匹配字符串

#正则表达式的简化
"^Mon|^Tue|^Wed|^Thu|^Fri|^Sat|^Sun"
"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)"
=========================================================


import re
data = 'Wed Mar 20 13:40:35 2002::geom@mnfdlm.edu::1016602835-4-6'


patt='^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)'
m=re.match(patt,data)

print(
m.group(),
m.group(1),
m.groups()
)
=====================================
Wed Wed ('Wed',)

分组 ^()

当地的日期和缩写,可以是^\w{3}

import re
data='Wed Mar 20 13:40:35 2002::geom@mnfdlm.edu::1016602835-4-6'

patt = '^(\w{3})'
m = re.match(patt, data)
if m is not None: print(m.group())
print(m.group(1))


================================
Wed
Wed

当{3}在圆括号中时,先匹配三个连续的字母数字字符,然后表示为一个分组。但是如果将{3}移到外部,它就等效于三个连续的单个字母数字字符。

group(1)访问子组1时,子组1被持续被下一个字符替换。

换句话说:这些是单个字母数字字符的三个独立(并且重叠)分组,与一个包含三个连续字母数字字符的单独分组相反。

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

patt = '^(\w){3}'
m = re.match(patt, data)
if m is not None: print(m.group())
print(m.group(1))


===============================================
Thu
u

搜索、匹配与贪婪

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

patt = '\d+-\d+-\d+'
m = re.search(patt, data)
if m is not None: print(m.group())
    
==========================================
1171590364-6-8

若用match()匹配则返回None。

re.match('.+(\d+-\d+-\d+)',data).group(1) 正则表达式从左至右扫描求值,并且试图获取尽可能多的字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9yCmdmtI-1612699840558)(Python核心编程(第三版).assets/image-20210207180527623.png)]

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

m = re.match('.+\d+-\d+-\d+',data).group()
j = re.match('.+(\d+-\d+-\d+)',data).group(1)

print(m,'\n'*2,j)
============================================
Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8 

 4-6-8

书中错误:strip('::') 为删除首尾要求符号,直到首位要求不存在为止。详见菜鸟教程

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

S1 = re.split('::',data)
S2 = S1[2]              					#1171590364-6-8
#S3_zhi = re.match('\d+-\d+-\d+',S2).group()

print(S2)

==================================
1171590364-6-8

print(m.group(1))

===============================================
Thu
u


搜索、匹配与贪婪
---

```python
import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

patt = '\d+-\d+-\d+'
m = re.search(patt, data)
if m is not None: print(m.group())
    
==========================================
1171590364-6-8

若用match()匹配则返回None。

re.match('.+(\d+-\d+-\d+)',data).group(1) 正则表达式从左至右扫描求值,并且试图获取尽可能多的字符串

[外链图片转存中…(img-9yCmdmtI-1612699840558)]

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

m = re.match('.+\d+-\d+-\d+',data).group()
j = re.match('.+(\d+-\d+-\d+)',data).group(1)

print(m,'\n'*2,j)
============================================
Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8 

 4-6-8

书中错误:strip('::') 为删除首尾要求符号,直到首位要求不存在为止。详见菜鸟教程

import re
data='Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8'

S1 = re.split('::',data)
S2 = S1[2]              					#1171590364-6-8
#S3_zhi = re.match('\d+-\d+-\d+',S2).group()

print(S2)

==================================
1171590364-6-8

本文链接: http://www.dtmao.cc/news_show_2000328.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?