千家信息网

Python怎么利用re模块实现简易分词

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本文小编为大家详细介绍"Python怎么利用re模块实现简易分词",内容详细,步骤清晰,细节处理妥当,希望这篇"Python怎么利用re模块实现简易分词"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢
千家信息网最后更新 2026年11月01日Python怎么利用re模块实现简易分词

本文小编为大家详细介绍"Python怎么利用re模块实现简易分词",内容详细,步骤清晰,细节处理妥当,希望这篇"Python怎么利用re模块实现简易分词"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

一个简单的tokenizer

分词(tokenization)任务是Python字符串处理中最为常见任务了。我们这里讲解用正则表达式构建简单的表达式分词器(tokenizer),它能够将表达式字符串从左到右解析为标记(tokens)流。

给定如下的表达式字符串:

text = 'foo = 12 + 5 * 6'

我们想要将其转换为下列以序列对呈现的分词结果:

tokens = [('NAME', 'foo'), ('EQ', '='), ('NUM', '12'), ('PLUS', '+'),\    ('NUM', '5'), ('TIMES', '*'), ('NUM', '6')]

要完成这样的分词操作,我们首先需要定义出所有可能的标记模式(所谓模式(pattern),为用来描述或者匹配/系列匹配某个句法规则的字符串,这里我们用正则表达式来做为模式),注意此处要包括空格whitespace,否则字符串中出现任何模式中没有的字符后,扫描就会停止。因为我们还需要给标记以NAME、EQ等名称,我们采用正则表达式中的命名捕获组来实现。

import reNAME = r'(?P[a-zA-Z_][a-zA-Z_0-9]*)' # 这里?P表示模式名称,()表示一个正则表达式捕获组,合在一起即一个命名捕获组EQ = r'(?P=)'NUM = r'(?P\d+)' #\d表示匹配数字,+表示任意数量PLUS = r'(?P\+)' #需要用\转义TIMES = r'(?P\*)' #需要用\转义WS = r'(?P\s+)' #\s表示匹配空格, +表示任意数量master_pat = re.compile("|".join([NAME, EQ, NUM, PLUS, TIMES, WS]))  # | 用于选择多个模式,表示"或"

接下来我们用模式对象中的scanner()方法来完成分词操作,该方法创建一个扫描对象:

scanner = master_pat.scanner(text)

然后可以用match()方法获取单次匹配结果,一次匹配一个模式:

scanner = master_pat.scanner(text)m = scanner.match() print(m.lastgroup, m.group()) # NAME foom = scanner.match()print(m.lastgroup, m.group()) # WS

当然这样一次一次调用过于麻烦,我们可以使用迭代器来批量调用,并将单次迭代结果以具名元组形式存储

Token = namedtuple('Token', ['type', 'value'])def generate_tokens(pat, text):    scanner = pat.scanner(text)    for m in iter(scanner.match, None):        #scanner.match做为迭代器每次调用的方法,        #None为哨兵的默认值,表示迭代到None停止        yield Token(m.lastgroup, m.group())    for tok in generate_tokens(master_pat, "foo = 42"):    print(tok)

最终显示表达式串"foo = 12 + 5 * 6"的tokens流为:

Token(type='NAME', value='foo')Token(type='WS', value=' ')Token(type='EQ', value='=')Token(type='WS', value=' ')Token(type='NUM', value='12')Token(type='WS', value=' ')Token(type='PLUS', value='+')Token(type='WS', value=' ')Token(type='NUM', value='5')Token(type='WS', value=' ')Token(type='TIMES', value='*')Token(type='WS', value=' ')Token(type='NUM', value='6')

过滤tokens流

接下来我们想要过滤掉空格标记,使用生成器表达式即可:

tokens = (tok for tok in generate_tokens(master_pat, "foo = 12 + 5 * 6")          if tok.type != 'WS')for tok in tokens:    print(tok)

可以看到空格被成功过滤:

Token(type='NAME', value='foo')Token(type='EQ', value='=')Token(type='NUM', value='12')Token(type='PLUS', value='+')Token(type='NUM', value='5')Token(type='TIMES', value='*')Token(type='NUM', value='6')

注意子串匹配陷阱

tokens在正则表达式(即"|".join([NAME, EQ, NUM, PLUS, TIMES, WS]))中顺序也非常重要。因为在进行匹配时,re模块就会按照指定的顺序对模式做匹配。故若碰巧某个模式是另一个较长模式的子串时,必须保证较长的模式在前面优先匹配。如下面分别展示正确的和错误的匹配方法:

LT = r'(?P<)'LE = r'(?P<=)'EQ = r'(?P>=)'master_pat = re.compile("|".join([LE, LT, EQ]))  # 正确的顺序master_pat = re.compile("|".join([LT, LE, EQ]))  # 错误的顺序

第二种顺序的错误之处在于,这样会把'<='文本匹配为LT('<')紧跟着EQ('='),而没有匹配为单独的LE(<=)。

我们对于"有可能"形成子串的模式也要小心,比如下面这样:

PRINT = r'(?Pprint)'NAME = r'(?P[a-zA-Z_][a-zA-Z_0-9]*)'master_pat = re.compile("|".join([PRINT, NAME]))  # 正确的顺序for tok in generate_tokens(master_pat, "printer"):    print(tok)

可以看到被print实际上成了另一个模式的子串,导致另一个模式的匹配出现了问题:

# Token(type='PRINT', value='print')# Token(type='NAME', value='er')

更高级的语法分词,建议采用像PyParsing或PLY这样的包。特别地,对于英文自然语言文章的分词,一般被集成到各类NLP的包中(一般分为按空格拆分、处理前后缀、去掉停用词三步骤)。对于中文自然语言处理分词也有丰富的工具(比如jieba分词工具包)。

读到这里,这篇"Python怎么利用re模块实现简易分词"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

模式 表达式 字符 顺序 字符串 方法 正则 空格 模块 文章 标记 处理 迭代 简易 结果 错误 接下来 任务 内容 名称 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 精品咖啡豆 科技金融是不是互联网金融 互联网是不是新科技 智能科技公司是互联网公司吗 互联网巨头科技公司 碳银互联网科技 卓越科技(互联网 ) 现代互联网科技股 互联网公司科技股 注册互联网科技公司经营范围大全 明优互联网科技有限公司 伊宁互联网科技做什么的 江苏互联网科技小贷 上海乐五互联网科技有限公司 抖集互联网科技技术咨询 云鲸互联网络科技有限公司 万物互联网智能科技 求路客互联网科技电话 深圳互联网科技园地址 华人运通互联网科技公司 互联网和科技创新 金融科技 互联网金融 广州互联网络科技有限公司 银川新华互联网科技职业技术培训学校图片 高科技互联网发展前景如何 为客找房互联网科技公司怎么样 福建互联网展示科技馆设计 西安左小互联网科技有限公司 众联互联网络科技 科技互联网公司两年变化
0