spaCy&x27;s regex不同于Python';s正则表达式

spaCy&x27;s regex不同于Python';s正则表达式,python,regex,spacy,Python,Regex,Spacy,我有以下文字 text = 'Monday to Friday 12 midnight to 5am 30% . Midnight Friday to 6am Saturday 30% . 9pm Saturday to Midnight Saturday 25% . Midnight Saturday to 6am Sunday 100% . 6am Sunday to 9pm Sunday 50%' 当我使用普通正则表达式时,我得到了以下结果 import re regex = '\d{1

我有以下文字

text = 'Monday to Friday 12 midnight to 5am 30% . Midnight Friday to 6am Saturday 30% . 9pm Saturday to Midnight Saturday 25% . Midnight Saturday to 6am Sunday 100% . 6am Sunday to 9pm Sunday 50%'
当我使用普通正则表达式时,我得到了以下结果

import re
regex = '\d{1}[a|p]m'
re.findall(regex, text)

# Returned:
['5am', '6am', '9pm', '6am', '6am', '6pm']
然而,当我在spaCy中使用相同的
regex
时,我没有得到任何回报

from spacy.matcher import Matcher
nlp = spacy.load('en_core_web_lg')

matcher = Matcher(nlp.vocab)
pattern = [{'TEXT': {'REGEX': '\d{1}[a|p]m'}}]
matcher.add('TIME', None, pattern)

doc = nlp(text)
matches = matcher(doc)

for match_id, start, end in matches:
    matched_span = doc[start:end]
    print(matched_span.sent.text)

这是否意味着我们不能将普通正则表达式与spaCy一起使用?如果是这样,你知道我在哪里可以学习spaCy的特殊正则表达式语法吗?谢谢。

您需要记住,这里的数字和字母是分开的,请参阅测试:

doc = nlp("1pm")
print([token.text for token in doc]) # => ['1', 'pm']
根据:

如果spaCy的标记化与模式中定义的标记不匹配,则该模式不会产生任何结果

您需要使用基于规则的匹配来定义自己的实体:

pattern = [{'LIKE_NUM': True}, {'LOWER': {'REGEX' : '^[ap]m$'}}]
然后将其添加到matcher:

matcher.add('TIME', None, pattern)
并获取匹配项:

for match_id, start, end in matches:
    span = doc[start:end]  # The matched span
    print(span.text)
完整演示:

import spacy
from spacy.matcher import Matcher

nlp = spacy.load("en_core_web_sm")

text = 'Monday to Friday 12 midnight to 5am 30% . Midnight Friday to 6am Saturday 30% . 9pm Saturday to Midnight Saturday 25% . Midnight Saturday to 6am Sunday 100% . 6am Sunday to 9pm Sunday 50%'
doc = nlp(text)

matcher = Matcher(nlp.vocab)
pattern = [{'LIKE_NUM': True}, {'LOWER': {'REGEX' : '^[ap]m$'}}]
matcher.add('TIME', None, pattern)

matches = matcher(doc)
print([doc[start:end] for match_id, start, end in matches])
#=> [5am, 6am, 9pm, 6am, 6am, 9pm]

仅供参考:“正常”正则表达式可以是
regex=r'\d[ap]m'
。根据文档,您似乎使用了错误的正则表达式:“当使用
REGEX
运算符时,请记住它对单个令牌而不是整个文本进行操作。您提供的每个表达式都将在标记上匹配。如果需要匹配整个文本,请参阅上的详细信息。“@WiktorStribiżew虽然你在技术上是正确的,但这很可能是对不正确的正则表达式的更正,因为它不包括上午11点和下午12点谢谢,@MonkeyZeus。起初,我很困惑,不明白你所说的
单一代币是什么意思,而不是整个文本的意思,因为我认为上午6点、下午6点等都是单一代币。只有在读到维克托的答案时,我才意识到斯帕西将它们视为2,而不是1。我想知道为什么spaCy会这样做,因为我觉得这似乎不自然。您好,Wiktor,感谢您不仅提供了解决方案,而且还向我展示了下次如何解决问题。非常感谢你的帮助。Regex本身就是一个挑战(不仅对我来说,我想对很多其他人来说也是如此),那么将它与spaCy结合起来是我力所不及的!比如说,如果你想匹配模式,你会使用哪一种:regex还是spaCy,原因是什么?@Nemo spaCy比regex更强大,所以这完全取决于你需要什么。如果需要提取、替换、删除或标记一些已知的或多或少简单的模式,可以使用regex。如果您需要更具体和语言感知的标记化,并且需要NLP的全部功能,那么您应该继续使用Spacy。