我如何修改此正则表达式模式,以便一旦找到匹配项,就返回整个句子,而不仅仅是匹配的单词?

时间:2018-08-13 13:34:44

标签: python regex

正如标题所说明的,此正则表达式模式主要检查描述变量以匹配集合中的单词组合,例如:

set = ["oak", "wood"]

然后,如果在5个单词间隔内找到了这2个单词,它将返回这些单词。但是,我需要它来返回匹配的句子。因此,例如,描述为:

description = "...would be a lovely addition to any home. This lovely oak hard wood table comes in a variety of sizes. Another great reason to consider..." 

我不仅希望返回匹配的单词,还希望它返回包含关键字的整个句子。

这是我目前正在使用的东西,显然只是返回了匹配的集合对。

re.findall(r"\b(?:(%s)\W+(?:\w+\W+){0,5}?(%s)|(%s)\W+(?:\w+\W+){0,5}?(%s))\b" % (set[0], set[1], set[1], set[0]), description)

我也知道,我相信这种模式在匹配时看起来会超出单个句子,因此您可能会遇到一种情况,即它在2个不同的句子中找到匹配项。如果可能的话,我还想找到一种将匹配限制为只能在同一句子内进行的方法。

我很乐意为此提供任何帮助。

编辑:只是为了阐明我想要的输出是:

"This lovely oak hard wood table comes in a variety of sizes."

因为这是包含匹配关键字对的句子。

谢谢!

5 个答案:

答案 0 :(得分:4)

根据我的评论,一些使用nltk的伪代码(目前无法访问Python

from nltk import sent_tokenize

for sent in sent_tokenize(your_data_here):
    if any(['foo', 'bar']) in sent:
        # do sth. useful here

很明显,您甚至可以在sent上使用您的初始正则表达式(毕竟这是一个字符串)。

答案 1 :(得分:3)

您可以使用以下RegEx:

print(re.findall(r"(^|(?<=\.))([a-zA-Z0-9\s]*oak[a-zA-Z0-9\s]*wood.*?(?=\.|$)).*?|([a-zA-Z0-9\s]*wood[a-zA-Z0-9\s]*oak.*?(?=\.|$))", description))

其中:

r"(^|(?<=\.))" # means start with 'start of string' or '.'
r"([a-zA-Z0-9\s]*oak[a-zA-Z0-9\s]*wood.*?(?=\.)).*?" # means any letter/number/space followed bi 'oak', followed by any letter/number/space, followed by wood, stopping at the first occurrence of a '.' or 'end of line'
r"([a-zA-Z0-9\s]*wood[a-zA-Z0-9\s]*oak.*?(?=\.|$))" # same as previous, but with | (or) condition matches the wood-oak case

输出:

  

('','这张可爱的橡木硬木桌有各种尺寸',   '')

答案 2 :(得分:1)

使用正则表达式是否必须?我发现仅使用以下内容会更严格:

set = ["oak","wood"]
description = "...would be a lovely addition to any home. This lovely oak hard wood table comes in a variety of sizes. Another great reason to consider..."

description2 = "...would be a lovely addition to any home. This is NOT oak however we do make other varieties that use cherry for a different style of hard wood."

def test_result(desc):
    desc = desc.split(". ")
    for sent in desc:
        if all(s in sent for s in set):
            if -5 <= sent.split(" ").index("oak") - sent.split(" ").index("wood") <= 5:
                print (sent)

test_result(description)
test_result(description2)

结果:

This lovely oak hard wood table comes in a variety of sizes

答案 3 :(得分:1)

您可以尝试使用以下正则表达式:

df = pd.DataFrame({'columnOne': ['TAG', '1111', 'system']}) def ids_replace(x): try: int(x) return 'ID' except ValueError: return x print(df.apply(ids_replace, axis=1)) > columnOne 0 TAG 1 ID 2 system

Demo with several examples

说明:

[^.]*?\boak(?:\W+[^\W.]+){0,5}?\W+wood(?:\W+[^\W.]+){0,5}?\W+table(?:\W+[^\W.]+){0,5}?\W+variety[^.]*\.+

答案 4 :(得分:0)

您可以通过在结尾处查找句点来捕获整个句子。您还可以通过将\W(匹配非单词字符)替换为[^.\w](匹配不是句点或单词字符的任何字符),使其从中间排除句点。

"(^|\.)([^.]*\b(?:(%s)[^.\w]+(?:\w+[^.\w]+){0,5}?(%s)|(%s)[^.\w]+(?:\w+[^.\w]+){0,5}?(%s))\b[^.]*)(\.|$)"

(^|\.)将匹配输入的开头或句点,而(\.|$)将匹配输入的句点或结尾(如果在最后一个句点之后输入)。

我现在无法在python中进行测试,但是即使我遇到错误或错字,它也可以为您指明正确的方向。