0

我一直被这个正则表达式所困扰

# Find the following keywords: sea, sear, search, 
# Find all overlapping keywords 
p = re.compile(r'(sea)+(r?((ch)?))')

pos = 0
while pos<len(s):
    m = p.search(s,pos)
    if m:
       pos = m.end()
       w = m.group()
       g = m.groups()
       #print w,g
       for k in range(len(g)):
         if g[k]:
             w += ', '+g[k]
             print w
         else:
           break

s ='search for searing remarks that mark whether the ark came by sea'

我也需要找到所有重叠的关键字。但是我的尝试产生了

search, sea
search, sea, rch
search, sea, rch, ch
sear, sea
sear, sea, r
sea, sea

我应该如何处理它。我今天才学的。提前致谢

预期结果:sea,sear, search for first 'search' searing 应该产生 sear, sea

4

2 回答 2

2

您当前的正则表达式应该能够检测到sea,searsearch. 但是,有一个小问题:

(sea)+(r?((ch)?))
     ^  ^     ^
     2  1     1

在我标记的 2 点上1,您允许seach与您的正则表达式匹配。由于rch都是可选的,它允许seach.

您允许sea重复,这意味着seaseasear可以匹配。好吧,这并没有那么大的灾难,您仍然可以确定重复多少次,但是很不方便。

修正了一点:

sea(r(ch)?)?

使用上面的正则表达式,由于?是贪婪的,它会在回溯匹配空字符串的情况之前尝试匹配。因此,搜索顺序是search--> sear--> sea

由于该re.search方法不允许多个匹配从同一索引开始,因此需要在单个匹配中处理它们。我想不出任何直接给出结果的方法。可能检查和推断是这里的唯一方法。

有很多方法可以检查这里匹配的内容。检查组 0 中字符串的长度是一种方法。另一种方法是检查组 2 和组 1 中匹配的内容。

于 2013-09-18T07:18:31.643 回答
1

您可能正在寻找一个后视断言。看这里

您还应该将您的“r”和“ch”组转换为第一个捕获组中的非捕获组,如下所示(假设单词边界始终是空格,您可以轻松概括这一点):

p = re.compile("(sea(?:r(?:ch)?)?) ")

如果您的关键字始终是一个前缀链,那么您通过对字符串中的每个位置进行迭代来浪费时间。您只是想匹配从最大到最小的前缀(即,最大的将首先匹配):

p = re.compile("(search|sear|sea)")

然后,您可以使用函数来拆分较大的前缀。

于 2013-09-18T06:55:02.380 回答