Skip to main content
 首页 » 编程设计

python之正则表达式让 3 个词彼此靠近。如何获取他们的上下文

2025年05月04日24mq0036

我有以下字符串:

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”和“garlic”彼此靠近的位置。所以我使用这个正则表达式:

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')] 

现在,我需要的是文本中这些词彼此接近的部分。我尝试对文本进行标记化,并遍历列表以查看每个句子中是否包含该单词,然后将其打印出来,但这会在文本开头捕获错误的“卡纸”。这不是我需要的 - 我只需要包含所有 3 个彼此接近的单词的文本。

一旦在文本中找到接近的 3 个词,是否有某种方法可以在前面说 10 个词,在后面说 10 个词?或者我怎样才能得到包含这些词的句子,(而不是得到包含它们但不相关的句子,比如本文的第一句)?

请您参考如下方法:

对于这样的问题,您需要确保匹配中有 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