正则表达式彼此相距3个字。如何获得他们的背景?

时间:2015-03-23 11:27:54

标签: python regex

我有以下字符串:

text = "I love jam. I like all other kinds of confectionery as well--cakes and croissants and things. Bagels too! Carbs for the win I say. And my other favorite kinds of food are mostly bread based - bread itself, so many different kinds of bread. I love the ones with herbs and cheese in it. I like pizza as well, and garlic bread. But most of all, jam."

现在,我想确定3个单词的位置," jam"," pizza"和#"大蒜"彼此靠近。所以我使用这个正则表达式:

fav_food = re.findall(r"\b(?:(?:((?i)pizza|pasta)|((?i)mint|garlic)|((?i)jam|jelly)|(?(1)|(?(2)|(?(3)|(?!))))\w+)\b\W*?){3,25}(?(1)(?(2)(?(3)|(?!))|(?!))|(?!))", text)

这给出了以下输出:

[('pizza', 'garlic', 'jam')]

现在,我需要的是文本中这些单词彼此接近的部分。我尝试对文本进行标记,然后遍历列表以查看每个句子中是否包含该单词,然后打印出该单词,但是这样可以捕获错误的#34; jam"在文本的开头。这不是我需要的 - 我只需要包含所有3个单词彼此接近的文本。

一旦在文本中找到了3个单词,有没有办法说出之前的10个单词和之后的10个单词?或者我怎样才能得到包含这些单词的句子(没有得到包含它们但不相关的句子,例如本文第一句)?

1 个答案:

答案 0 :(得分:1)

对于这样的问题,你需要确保你的匹配中有3个单词,它应该是最小长度。对于我们问题的第一部分,我们需要一个匹配我们的单词和其他单词的任何组合的模式,它也必须包含所有单词,所以你不能做类似的事情:

(pizza|garlic|jam).*?(pizza|garlic|jam).*?(pizza|garlic|jam)

因为它会匹配jam ...pizza...jam之类的内容。您需要为正则表达式创建可以使用itertools.permutations创建的所有可能性,因此您必须选择以下某种情况:

(pizza.*?garlic.*?jam)|(pizza.*?jam.*?garlic)|(garlic.*?pizza.*?jam)|(garlic.*?jam.*?pizza)|(jam.*?pizza.*?garlic)|(jam.*?garlic.*?pizza)

注意在前面的组中你想要最小匹配,所以你必须要有一个单词在前导中,一个在尾随句子(因为如果你有另一个单词肯定是多余的考虑(this is jam and pizza and garlic)这句话this is是多余的)所以我们在这里创建了所有可能性优化我们的正则表达式以拒绝额外搜索

>>> l=('pizza', 'garlic', 'jam')
>>> p=[]
>>> for i,j,k in permutations(l,3) :
...     m=re.search(r'({}.*?{}.*?{})'.format(i,j,k),text)
...     if m :
...        p.append(m.group(0))
... 
>>> print min(p,key=len)
pizza as well, and garlic bread. But most of all, jam