【问题标题】:Regex pattern for abbreviation and punctuation mark缩写和标点符号的正则表达式模式
【发布时间】:2018-02-24 06:34:40
【问题描述】:

我有一个段落,我想通过将标点符号与单词分开来标记它,并打印结果。有特殊情况(缩写如 U.S.A 和撇号如 Peter's 和十进制数字)应附在字母后,而不是分开。

我运行以下代码:

import re

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. 
Peter's house!  3,500 calorie rule, which equates a weight alteration 
of 2.2 lb"

pattern = r"""(?:[A-Z]\.)+ |\d+(?:\.\d+)?%?|\w/.+$\s-|\w+(?:[-']\w+)*|
(?:[+/\-@&*]|/.$/)"""

print (re.findall(pattern, text))

输出:

['My', 'weight', 'is', 'about', '68', 'kg', '+', '/', '-', '10', 
 'grams', 'I', 'live', 'in', 'U.S.A. ', 'at', 'Mr', "Peter's", 'house',
 '3', '500', 'calorie', 'rule', 'which', 'equates', 'a', 'weight',
 'alteration', 'of', '2.2', 'lb'
]

这段代码有一些错误,我真的需要帮助来修复它们:

  1. 它会删除所有的标点符号!我想保留它们但与文字分开。

  2. 该模式忽略包含 (,) 的数字并将其删除。我在模式中添加了\d+(?:\,\d+)?%?,但它不能正常工作。

  3. 该模式也会忽略一些缩写,例如Mr.

非常感谢您的帮助!

【问题讨论】:

  • 我不认为这是完全可能的。正则表达式应该如何知道“U.S.A.”的最后一点是不是句末?

标签: python regex nltk


【解决方案1】:

我建议您避免尝试使用正则表达式来执行此操作,并使用专为该工作设计的工具。以下应处理U.S.A.Peter's

from nltk.tokenize import WhitespaceTokenizer, word_tokenize

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. Peter's house!  3,500 calorie rule, which equates a weight alteration of 2.2 lb"

print WhitespaceTokenizer().tokenize(text)
print word_tokenize(text)

这将为您提供以下可能性:

['My', 'weight', 'is', 'about', '68', 'kg,', '+/-', '10', 'grams!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', "Peter's", 'house!', '3,500', 'calorie', 'rule,', 'which', 'equates', 'a', 'weight', 'alteration', 'of', '2.2', 'lb']
['My', 'weight', 'is', 'about', '68', 'kg', ',', '+/-', '10', 'grams', '!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', 'Peter', "'s", 'house', '!', '3,500', 'calorie', 'rule', ',', 'which', 'equates', 'a', 'weight', 'alteration', 'of', '2.2', 'lb']

【讨论】:

  • 好的,我肯定会使用这个工具,但是输出有错误。 “克!”中的标点符号!和“房子!”应该从这个词中溢出。所以,正确的输出应该是“克”、“!”、“房子”、“!”在这种情况下,我可以在这段代码中使用正则表达式吗?
  • 您也可以调查word_tokenize() 作为替代方案。我已经更新了脚本。
  • 感谢您的更新。第二个输出中的问题是名称中的撇号 Peter's 是分开的,它不应该。 “彼得”、“的”
  • 我将此添加到代码中以修复撇号,但它不起作用。模式= (r"(?:[^\W\d_](?:[^\W\d_]|['\-])+[^\W\d])") nltk.regexp_tokenize(文本,模式)
【解决方案2】:

如果您不打算使用成熟的自然语言处理工具,我建议您使用更简单的模式并计划一些解析后清理。尝试解决模式匹配中的所有问题是很棘手的,并且随着新语法元素的引入,可能会继续失败。也就是说,这是一种更简单的模式方法,我相信它可以处理您关心的大多数异常:

import re

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. Peter's house!  3,500 calorie rule, which equates a weight alteration of 2.2 lb"

pattern = r"(\s+|(?:[A-Z']\.?)+)"

tokens = [token for token in re.split(pattern, text, flags=re.I) if token and not token.isspace()]

print(tokens)

输出

['My', 'weight', 'is', 'about', '68', 'kg', ',', '+/-', '10', 'grams',
'!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', "Peter's", 'house', '!',
'3,500', 'calorie', 'rule', ',', 'which', 'equates', 'a', 'weight',
'alteration', 'of', '2.2', 'lb']

而不是re.findall(),我使用re.split() 和模式保留来隔离字符串中的标记(即我们按单词拆分。)当出现新的异常时,评估是否值得使模式复杂化或者它们是否可以处理前或后解析。

【讨论】:

  • 非常感谢您提供的代码。它可以作为我想要的输出正常工作。我想知道如果我想使用 nltk.tokenize 怎么办。我也应该使用正则表达式吗?否则代码会简单得多
  • 我将 nltk & python 3 与您的模式 regexp_tokenize(text, pattern=("\s+|(?:[A-Z']\.?)+")) 一起使用,但它向我展示了这个:['M','','','','','','','','','','I','','','','USA' ,'','','M','','P',"'",'','','','','','','','','',' ', ' ', ' ']
  • @BeautifulMind,正如我在解释中指出的那样,我的模式是为re.split() 设计的,它应用模式不同于其他正则表达式函数,然后是删除空字符串和空格的理解。 regexp_tokenize() 函数以不同的方式应用模式,即summarized in the code comments at the top of the regexp_tokenize() source file.
  • 感谢您的回答!我真的很感激。
猜你喜欢
  • 2012-07-27
  • 1970-01-01
  • 2012-03-19
  • 2013-11-22
  • 2013-05-12
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
相关资源
最近更新 更多