NLTK 正则表达式标记器在正则表达式中不能很好地处理小数点

Posted

技术标签:

【中文标题】NLTK 正则表达式标记器在正则表达式中不能很好地处理小数点【英文标题】:NLTK regexp tokenizer not playing nice with decimal point in regex 【发布时间】:2014-04-06 05:20:15 【问题描述】:

我正在尝试编写一个文本规范器,需要处理的基本情况之一是将3.14 转换为three point one fourthree point fourteen

我目前正在使用模式\$?\d+(\.\d+)?%?nltk.regexp_tokenize,我认为它应该可以处理数字以及货币和百分比。但是,目前,$23.50 之类的东西处理得很好(它解析为['$23.50']),但3.14 正在解析为['3', '14'] - 小数点被删除了。

我尝试在我的正则表达式中添加一个单独的模式 \d+.\d+,但这没有帮助(我当前的模式不应该已经匹配了吗?)

编辑 2:我还刚刚发现 % 部分似乎也无法正常工作 - 20% 仅返回 ['20']。我觉得我的正则表达式一定有问题,但我已经在 Pythex 中测试过,看起来还不错?

编辑:这是我的代码。

import nltk
import re

pattern = r'''(?x)    # set flag to allow verbose regexps
            ([A-Z]\.)+        # abbreviations, e.g. U.S.A.
            | \w+([-']\w+)*        # words w/ optional internal hyphens/apostrophe
            | \$?\d+(\.\d+)?%?  # numbers, incl. currency and percentages
            | [+/\-@&*]         # special characters with meanings
            '''
    words = nltk.regexp_tokenize(line, pattern)
    words = [string.lower(w) for w in words]
    print words

这是我的一些测试字符串:

32188
2598473
26 letters from A to Z
3.14 is pi.                         <-- ['3', '14', 'is', 'pi']
My weight is about 68 kg, +/- 10 grams.
Good muffins cost $3.88 in New York <-- ['good', 'muffins', 'cost', '$3.88', 'in', 'new', 'york']

【问题讨论】:

?是非贪婪的(最小匹配)尝试用 ,1 替换它 试试这个:(\$?\d+(?:\.\d+)?%?) 你能提供你用来测试这个的代码吗?我无法在这里重现该问题,23.50 美元和 3.14 美元都处理得很好 @gonz,我已经编辑了问题。 【参考方案1】:

罪魁祸首是:

\w+([-']\w+)*

\w+ 将匹配数字,因为那里没有 .,它只会匹配 3.14 中的 3。稍微移动选项,使\$?\d+(\.\d+)?%? 位于上述正则表达式部分之前(以便首先在数字格式上尝试匹配):

(?x)([A-Z]\.)+|\$?\d+(\.\d+)?%?|\w+([-']\w+)*|[+/\-@&*]

regex101 demo

或扩展形式:

pattern = r'''(?x)               # set flag to allow verbose regexps
              ([A-Z]\.)+         # abbreviations, e.g. U.S.A.
              | \$?\d+(\.\d+)?%? # numbers, incl. currency and percentages
              | \w+([-']\w+)*    # words w/ optional internal hyphens/apostrophe
              | [+/\-@&*]        # special characters with meanings
            '''

【讨论】:

伟大的收获!很容易忘记顺序在匹配中很重要。 就是这样。很好的答案。是的,顺序很重要,在这个简单的 OR 中,一旦正则表达式开始匹配,它就会继续消耗你的字符串,它不是最具体的匹配,而是第一个匹配当前字符的匹配。 @JessicaYang 好吧,如果你没有提交代码,我永远猜不到 :) 不客气! ^^ @Jerry 进行该更改破坏了我的序数 ('1st', '322nd') 解析器 - ['1','st'] - 并在其末尾添加了 \b$ 使我的序数回归,但现在百分比不'不像我期望的那样工作(20% 仅被捕获为20)。你知道是什么原因造成的吗? @JessicaYang \b% 和空格之间不匹配,因为它们都是非单词字符。尝试将其用于数字部分:\$?\d+\b(\.\d+)?%? 它会解决您当前遇到的问题,但我不知道它是否会解决未来的问题。也许你也需要一种不同的方法 =/【参考方案2】:

试试这个正则表达式:

\b\$?\d+(\.\d+)?%?\b

我用单词边界匹配包围初始正则表达式:\b

【讨论】:

以上是关于NLTK 正则表达式标记器在正则表达式中不能很好地处理小数点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 nltk 正则表达式模式来提取特定的短语块?

如何使用 NLTK 正则表达式模式用 UP/DOWN 指标注释财经新闻?

基于词汇和正则表达式矢量化文档

NLTK 正则表达式和 CFG

Python - 用于将文本拆分为句子的正则表达式(句子标记)[重复]

nltk 正则表达式分词器