正则表达式,用于在两个相同的单词之间进行搜索

时间:2016-03-14 20:41:17

标签: regex

鉴于文字:

PAGE 1
apple

PAGE 2
apple
banana

PAGE 3
orange

PAGE 4
banana

PAGE 5
pear

PAGE 6
apple
orange
banana
pea

我想要一个正则表达式,它会向我显示香蕉所在的每个页面,即第2页和第4页。

我尝试过的事情:

PAGE.*?banana.*?PAGE

但是返回第1页和第4页。

PAGE(?!.*?PAGE).*?banana

这是尝试向前看,并确保页面和香蕉字之间没有额外的页面,但这没有返回任何内容。

(?<=PAGE).*(?=banana)

借鉴Regex, get entire string between two keywords。这将返回PAGE 1,匹配最后一个香蕉和第一个PAGE之间的所有内容。

我认为环顾四周就是答案,但我无法理解如何将PAGE#与香蕉相匹配,但只有PAGE#香蕉才开启。我该怎么做?

5 个答案:

答案 0 :(得分:1)

试试这个正则表达式。

正则表达式: PAGE (\d+)\s[^ ]*(?=banana)[^ ]*\n

要使用的标志:

  • g进行全球搜索。

  • s允许.搜索换行。

使用\1$1抓取第一个群组。

Regex101 Demo

答案 1 :(得分:1)

很好用于re.finditer

txt="""\
PAGE 1
apple

PAGE 2
apple
banana

PAGE 3
orange

PAGE 4
banana

PAGE 5
pear"""

import re

tgt='banana'

for m in re.finditer(r'^PAGE\s+(\d+)\s+([\s\S]+?)(?=^PAGE|\Z)', txt, re.M):
    if re.search(r'(?i){}'.format(tgt), m.group(2)):
        print '"{}" found on Page {}'.format(tgt, m.group(1))

打印:

"banana" found on Page 2
"banana" found on Page 4

相同的技术可以在页面上生成每个水果的映射:

di={}
for m in re.finditer(r'^PAGE\s+(\d+)\s+([\s\S]+?)(?=^PAGE|\Z)', txt, re.M):
    for fruit in m.group(2).split():
        di.setdefault(fruit, []).append(m.group(1))
>>> di
{'orange': ['3'], 'pear': ['5'], 'apple': ['1', '2'], 'banana': ['2', '4']}

答案 2 :(得分:0)

尝试这种模式

(?<=PAGE )(\d+)(?=(?:[^P]|\bP(?!AGE\b))*\bbanana\b)  

Demo

答案 3 :(得分:0)

只是提供另一种选择,这也可行:

^PAGE\s+(?P<page>\d+)[\n\r] # match PAGE + whitespace + digit at the beginning of a line
(?s:                        # open a non-capturing, single-line parenthesis
    (?:.(?!^$))*?           # make not to match an empty line (lazily)
    \bbanana\b              # look for banana with word boundaries
    (?:.(?!^$))*?
)

请参阅a demo on regex101.com

答案 4 :(得分:-1)

这有效:

PAGE(?:(?PAGE)。)*?香蕉

感谢Wiktor关于使用驯化贪婪令牌解决方案的评论,我用Google搜索并找到了此页面:http://www.rexegg.com/regex-quantifiers.html#tempered_greed

全部谢谢!