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模块与正则表达式相关推荐

  1. python中怎样使用re模块_PYTHON正则表达式 re模块使用说明

    首先,运行 Python 解释器,导入 re 模块并编译一个 RE: #!python Python 2.2.2 (#1, Feb 10 2003, 12:57:01) >>> im ...

  2. 【Python笔记】使用 re 模块实现正则表达式操作

    使用 re 模块实现正则表达式操作 匹配字符串 使用 match() 方法进行匹配 使用 search() 方法进行匹配 使用 findall() 方法进行匹配 替换字符串 使用正则表达式分割字符串 ...

  3. python未读邮件_urllib2模块学习--爬虫读取163邮箱未读邮件

    在编写爬虫之前,先介绍个工具httpfox,是firefox的一个插件扩展,它是编写爬虫的神器啊. HttpFox 监控和分析浏览器和网络服务器之间收发的所有HTTP流量. 每个请求可得到的信息包括: ...

  4. python re模块_python 正则表达式 (重点) re模块

    京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示. 假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误. 这个功能是怎么实现的呢? 假如现在你用python ...

  5. python中match方法返回字符串的长度_Python re模块与正则表达式详解

    Python 中使用re模块处理正则表达式,正则表达式主要用来处理文本中的查找,匹配,替换,分割等问题:我们先来看一个问题,切入正则表达式. 问题: 匹配字符串,最少以3个数字开头.使用Python代 ...

  6. 初学者python笔记(re模块、正则表达式完全解析)

    文章目录 正则表达式与re模块 字符匹配 普通字符匹配 利用元字符进行模糊匹配 元字符: . ^ $ + ? {} [] | () \ 重复的字符匹配 re模块下的其他方法 今天总结一下正则表达式,它 ...

  7. python re 模块及正则表达式调用认识 (2)

    接<python re 模块及正则表达式调用认识> \number 匹配与前面组编号相匹配的文本.从1开始编号到99. For example, (.+) \1 matches 'thet ...

  8. Python爬虫学习笔记-第六课(正则表达式下+csv模块的使用)

    正则表达式下+csv模块的使用 1. re模块方法补充 1.1 compile()方法 1.2 search()和findall()方法 1.3 split()方法 1.4 sub()方法 2. re ...

  9. 初探Python字节码和dis模块

    本文主要介绍 Python 字节码.Python 虚拟机内幕以及 dis 模块的简单应用.阅读本文预计 10 min. 初探Python字节码和dis模块 1. 前言 2. Python 字节码 2. ...

最新文章

  1. 数学的关键是概念而非技巧
  2. 不知道这 7 大 OpenCV 函数怎么向计算机视觉专家进阶?
  3. 宏基因组合种树,2-4天领证
  4. 基于stm32f427实现SVPWM控制永磁同步开环转动
  5. 前端参数无法转为后端实体内部类_Spring Boot返回前端Long型丢失精度
  6. python不满足条件重新输入_如果Python中不满足条件,则拒绝用户输入
  7. 小说网jsp源码_基于jsp+mysql的JSP小说网
  8. linux vim (your system doesn't appear to have the zip pgm)
  9. 华为云全球首发企业级AI应用开发套件ModelArts Pro,加速行业AI落地
  10. Hive创建外部表以及分区
  11. spring快速入门(二)
  12. JavaScript高级技巧
  13. excel撤销工作保护(忘记密码)
  14. java随机生成中文姓名,性别,Email,手机号,住址 等
  15. 移动端input提起数字键盘如何设置小数点?
  16. Spark的位置优先: TaskSetManager 的有效 Locality Levels
  17. abb和plcsocket通讯_abb与西门子plc通讯问题
  18. python怎么选取不连续的列_用pandas中的DataFrame时选取行或列的方法
  19. 使用Python对植物大战僵尸学习研究
  20. 商业广告CPT-物料召回

热门文章

  1. 在桌面上用鼠标点击一个图标,结果附近若干个图标都被选中的原因?
  2. 友友车友软件 android,友友车友模拟学车软件2018
  3. android开发常用组件和第三方库(二)
  4. 佳能lbp2900+在win10下的安装
  5. iptables 端口转发
  6. AP Autosar平台设计 10 Persistency持久性/可靠性存储
  7. 【STM32】GPIO输入—按键检测
  8. linux安装打印机服务,archlinux安装打印机
  9. matplotlib 自带绘图样式效果展示速查(全)
  10. 在Vue中将文字以语音进行播报