python每日读02-re模块与正则表达式
python每日读02-re模块与正则表达式
例程学习与注释
检查对子
在这个例子里,我们可以使用以下辅助函数来更好的显示匹配对象
def displaymatch(match):if match is None:return Nonereturn '<Match: %r, groups=%r>' % (match.group(), match.groups())
假设你在写一个扑克程序,一个玩家的一手牌为五个字符的串,每个字符表示一张牌,“a” 就是 A, “k” K, “q” Q, “j” J, “t” 为 10, “2” 到 “9” 表示2 到 9。
要看给定的字符串是否有效,我们可以按照以下步骤
>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q")) # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e")) # Invalid.
>>> displaymatch(valid.match("akt")) # Invalid.
>>> displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"
最后一手牌,“727ak” ,包含了一个对子,或者两张同样数值的牌。要用正则表达式匹配它,应该使用向后引用如下
>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak")) # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak")) # No pairs.
>>> displaymatch(pair.match("354aa")) # Pair of aces.
"<Match: '354aa', groups=('a',)>"
要找到对子包含的是哪一张牌,应该按照下面的方式使用 group() 方法:
>>> pair.match("717ak").group(1)
'7'# Error because re.match() returns None, which doesn't have a group() method:
>>> pair.match("718ak").group(1)
Traceback (most recent call last):File "<pyshell#23>", line 1, in <module>re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'>>> pair.match("354aa").group(1)
'a'
模拟scanf()
下表提供scanf()格式符和正则表达式大致相同的映射
scanf()格式符 | 正则表达式 |
---|---|
%c | . |
%5c | .{5} |
%d | [-+]?\d+ |
%e, %E, %f, %g | [-+]?(\d+(\.\d*)?|\.\d+)([eE] [-+]?\d+)? |
%i | [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+) |
%o | [-+]?[0-7]+ |
%s | \S+ |
%u | \d+ |
%x, %X | [-+]?(0[xX])?[\dA-Fa-f]+ |
例子:从文件名和数字提取 字符串
/usr/sbin/sendmail - 0 errors, 4 warnings
#对以上一段文本进行匹配
#scanf()格式化格式如下
%s - %d errors, %d warnings
#等价正则表达式如下
(\s+) - (\d+) errors, (\d+) warnings
'''(\s+) \s匹配所有的Unicode字符,‘+’表示对其前方的正则表达式匹配任意多次
同理(\d+)
'''
建立一个电话本
原文本如下:
>>> text =
"""Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""
split()可以将字符串拆分成列表,从而便于修改文本的结构,十分有用。
>>> entries = re.split("\n+", text)
>>>#先将文本拆分成为一行一行的字段,而后对每一行就行正则匹配
>>> entries#展示拆分后的效果
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
>>> [re.split(":? ", entry, 4) for entry in entries]
#正则表达式":? "指匹配一个或者0个:后接一个空格的类似格式,即为可以匹配冒号空格,与纯空格两种情况。整句意为:以匹配的到的匹配对象为分割的标志,将整个entry文本分割四次。
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
同由此我们就将用户的名字、性氏、电话号码以及房间号分离出来了
文字整理
sub( )可以将字符中匹配到的样式替换为你自己想要的文字格式,以下整个例子就很哈的使用了sub( )。
>>> def repl(m):
... inner_word = list(m.group(2))#生成中间文本列表
... random.shuffle(inner_word)#将中间文本列表打乱
... return m.group(1) + "".join(inner_word) + m.group(3)
#返回一个中间的单词被打乱的字符串
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'''匹配单词的首字母,第二个到倒数第二个字母,以及尾字母,生成三个匹配组。分别为‘P’‘refesso’‘r’。将中间的字符串,在此例子中为‘refesso’,传入repl()函数中打乱,将打乱得到的字符串替换原本的中间的字符串(‘refesso’)
'''
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
整体操作
找到所有副词
findall( )将会匹配所有的能够同正则表达式匹配的字符串,而search( )只能够匹配第一个与正则表达式匹配的字符串,可以用作大批量文本的操作。
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)#这个则是匹配所有以ly结尾的字符串
['carefully', 'quickly']
找到所有副词和位置
finditer( )同findall( )的返回值不同,将会返回一个匹配对象,因此可以对匹配到的结果进行与匹配对象有关的相关操作。可以得到匹配对象在原文本中的位置等其它的详细信息
>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly", text):#同上匹配含义
... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly
原始字符记法
(r"text") 保持正则表达式正常。否则,每个正则式里的反斜杠(‘’) 都必须前缀一个反斜杠来转义。比如,下面两行代码功能就是完全一致的
>>> re.match(r"\W(.)\1\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
>>> re.match("\\W(.)\\1\\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
当需要匹配一个字符反斜杠,它必须在正则表达式中转义。在原始字符串记法,就是 r"\"。否则就必须用 “\\”,来表示同样的意思
>>> re.match(r"\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
>>> re.match("\\\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
写一个词法分析器
这个例子的目的是写一个词法器或者词法分析器分析自负床,并且分类为目录组
import collections
import reToken = collections.namedtuple('Token', ['type', 'value', 'line', 'column'])def tokenize(code):keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}token_specification = [('NUMBER', r'\d+(\.\d*)?'), # 整数或十进制数 \d+ 匹配整数或小数的整数部分# (\.\d*)\.匹配.字符,后借0到任意多位的整数# ? 最后的?表示(\.\d*)这一部分匹不匹配都行 ('ASSIGN', r':='), # Assignment operator''' 仅仅匹配=运算符'''('END', r';'), # Statement terminator'''仅匹配;'''('ID', r'[A-Za-z]+'), # Identifiers'''[A-Za-z]匹配一位英文字符,不论大小写+ 对[A-Za-z]进行1次到任意次的匹配'''('OP', r'[+\-*/]'), # Arithmetic operators'''直接匹配+ -(这里用了\来转义)* / 四个符号'''('NEWLINE', r'\n'), # Line endings'''直接匹配\n'''('SKIP', r'[ \t]+'), # Skip over spaces and tabs'''[ \t] 匹配空格即" "或者\t+ 对[A-Za-z]进行1次到任意次的匹配'''('MISMATCH', r'.'), # Any other character#'.'匹配除了换行符的任意字符]tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)#将所有正则表达式用或逻辑连接#(?P<%s>%s) 是(?P<name>...)的匹配形式,其中token_specification的每个元组的左侧字符串为name,右侧的正则表达式为...line_num = 1line_start = 0for mo in re.finditer(tok_regex, code):kind = mo.lastgroupvalue = mo.group()column = mo.start() - line_startif kind == 'NUMBER':value = float(value) if '.' in value else int(value)elif kind == 'ID' and value in keywords:kind = valueelif kind == 'NEWLINE':line_start = mo.end()line_num += 1continueelif kind == 'SKIP':continueelif kind == 'MISMATCH':raise RuntimeError(f'{value!r} unexpected on line {line_num}')yield Token(kind, value, line_num, column)statements = '''IF quantity THENtotal := total + price * quantity;tax := price * 0.05;ENDIF;
'''for token in tokenize(statements):print(token)
python每日读02-re模块与正则表达式相关推荐
- python中怎样使用re模块_PYTHON正则表达式 re模块使用说明
首先,运行 Python 解释器,导入 re 模块并编译一个 RE: #!python Python 2.2.2 (#1, Feb 10 2003, 12:57:01) >>> im ...
- 【Python笔记】使用 re 模块实现正则表达式操作
使用 re 模块实现正则表达式操作 匹配字符串 使用 match() 方法进行匹配 使用 search() 方法进行匹配 使用 findall() 方法进行匹配 替换字符串 使用正则表达式分割字符串 ...
- python未读邮件_urllib2模块学习--爬虫读取163邮箱未读邮件
在编写爬虫之前,先介绍个工具httpfox,是firefox的一个插件扩展,它是编写爬虫的神器啊. HttpFox 监控和分析浏览器和网络服务器之间收发的所有HTTP流量. 每个请求可得到的信息包括: ...
- python re模块_python 正则表达式 (重点) re模块
京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示. 假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误. 这个功能是怎么实现的呢? 假如现在你用python ...
- python中match方法返回字符串的长度_Python re模块与正则表达式详解
Python 中使用re模块处理正则表达式,正则表达式主要用来处理文本中的查找,匹配,替换,分割等问题:我们先来看一个问题,切入正则表达式. 问题: 匹配字符串,最少以3个数字开头.使用Python代 ...
- 初学者python笔记(re模块、正则表达式完全解析)
文章目录 正则表达式与re模块 字符匹配 普通字符匹配 利用元字符进行模糊匹配 元字符: . ^ $ + ? {} [] | () \ 重复的字符匹配 re模块下的其他方法 今天总结一下正则表达式,它 ...
- python re 模块及正则表达式调用认识 (2)
接<python re 模块及正则表达式调用认识> \number 匹配与前面组编号相匹配的文本.从1开始编号到99. For example, (.+) \1 matches 'thet ...
- Python爬虫学习笔记-第六课(正则表达式下+csv模块的使用)
正则表达式下+csv模块的使用 1. re模块方法补充 1.1 compile()方法 1.2 search()和findall()方法 1.3 split()方法 1.4 sub()方法 2. re ...
- 初探Python字节码和dis模块
本文主要介绍 Python 字节码.Python 虚拟机内幕以及 dis 模块的简单应用.阅读本文预计 10 min. 初探Python字节码和dis模块 1. 前言 2. Python 字节码 2. ...
最新文章
- 数学的关键是概念而非技巧
- 不知道这 7 大 OpenCV 函数怎么向计算机视觉专家进阶?
- 宏基因组合种树,2-4天领证
- 基于stm32f427实现SVPWM控制永磁同步开环转动
- 前端参数无法转为后端实体内部类_Spring Boot返回前端Long型丢失精度
- python不满足条件重新输入_如果Python中不满足条件,则拒绝用户输入
- 小说网jsp源码_基于jsp+mysql的JSP小说网
- linux vim (your system doesn't appear to have the zip pgm)
- 华为云全球首发企业级AI应用开发套件ModelArts Pro,加速行业AI落地
- Hive创建外部表以及分区
- spring快速入门(二)
- JavaScript高级技巧
- excel撤销工作保护(忘记密码)
- java随机生成中文姓名,性别,Email,手机号,住址 等
- 移动端input提起数字键盘如何设置小数点?
- Spark的位置优先: TaskSetManager 的有效 Locality Levels
- abb和plcsocket通讯_abb与西门子plc通讯问题
- python怎么选取不连续的列_用pandas中的DataFrame时选取行或列的方法
- 使用Python对植物大战僵尸学习研究
- 商业广告CPT-物料召回