匹配两个关键字之间的文本块,但如果关键字介于两者之间则不匹配

Match a block of text between a two key words, but not if a key word is in between

假设我有一个包含 cat 首诗的文本文件,需要找到所有以 dog 结尾的诗歌。这些诗都是以cat这个词开头的。如何只匹配以 cat 开头并以 dog 结尾的诗歌?

Cat poem: 
My feline is very furry
I like furry felines
This is why I do not have a dog

Cat poem:
Littly furry paws
this is what i like
I don't care if it's a feline or a canine

Cat poem:
The little felines
playing in the field
sitting on the side watching is a dog

在我的示例中,我希望匹配第一首和最后一首诗,而不要匹配中间的诗。如果所有的诗都以 dog 结尾,(?=cat).*?(?<=dog) 将是一个简单的解决方案(感谢 this answer)。然而,这首先匹配第一首诗,然后匹配第二首和第三首诗(因为第二首诗中没有 dog)。我尝试对该正则表达式的任何扩展都产生了相同的结果,例如(?=cat).*?(?!cat).*?(?<=dog).

我使用的是 Notepad++ (v6.5.2),所以任何答案都应该包括解决方案。如果其他环境允许更优雅的解决方案,请随意添加。

您可以使用 tempered greedy token 正则表达式来匹配从 Catdog 的不包含 Cat 的子字符串:

^Cat\b(?:(?!^Cat\b).)*\bdog\b(?=\R+Cat\b|\z)
必须选中

. 匹配换行符 选项。见 regex demo here.

模式分解:

  • ^ - 行首
  • Cat\b - 整个单词 Cat
  • (?:(?!^Cat\b).)* - 在行首
  • 匹配任何不是整个单词 Cat 的文本的缓和贪婪标记
  • \bdog\b - 一个完整的单词 dog...
  • (?=\R+Cat\b|\z) - 后跟 1+ 个换行符序列(\R+)然后是整个单词 Cat,或者在 [= 的末尾40=]file(\z\Z 是整个字符串结束锚点,只是 \Z 允许换行符紧跟其后)。