查找具有额外资格标准的所有比赛

给出句子如;

Boy has a dog and a cat. Boy microwaves a gerbil. Sally owns a cat. 

对于每个句子,我想要一个动物列表(定义为’狗”猫’或’沙鼠’),其中“男孩”是第一个单词。 对于上面的列表,将是;

 ['dog', 'cat'] ['gerbil'] 3rd sentence would not match. 

正则表达式;

 dog|cat|gerbil 

将返回所有匹配,但不是特定于男孩(第三句将返回不受欢迎的’猫’)。

 ^Boy.*(dog|cat|gerbil) 

返回最后一个匹配动物的整个短语,例如“Boy has a dog and a cat”,而第一个也是唯一一个组是“cat”。

如何获得与“男孩”相关的所有动物的列表(即以“男孩”开头的句子中的动物)?

您可以使用积极的观察:

 (?< =^Boy.*?)(?:dog|cat|gerbil) 

或者,带有单词边界的变体以匹配动物作为整个单词:

 (?< =^Boy\b.*?)\b(?:dog|cat|gerbil)\b 

请参阅正则表达式演示

(?< =^Boy.*?)正向后视将需要在字符串开头的Boy用于匹配消费模式。

如果您的输入包含LF(换行符)字符,请传递RegexOptions.Singleline选项. 也匹配换行符。

C#用法:

 var results = Regex.Matches(s, @"(?< =^Boy\b.*?)\b(?:dog|cat|gerbil)\b") .Cast() .Select(m => m.Value) .ToList(); 

C#演示 :

 var strs = new List() { "Boy has a dog and a cat.", "Boy something a gerbil.", "Sally owns a cat." }; foreach (var s in strs) { var results = Regex.Matches(s, @"(?< =^Boy\b.*?)\b(?:dog|cat|gerbil)\b") .Cast() .Select(m => m.Value) .ToList(); if (results.Count > 0) { Console.WriteLine("{0}:\n[{1}]\n------", s, string.Join(", ", results)); } else { Console.WriteLine("{0}:\nNO MATCH!\n------", s); } } 

输出:

 Boy has a dog and a cat.: [dog, cat] ------ Boy something a gerbil.: [gerbil] ------ Sally owns a cat.: NO MATCH! ------ 

还有一种方法 :匹配任何以Boy开头的字符串,然后在每次成功匹配后:

 (?:\G(?!\A)|^Boy\b).*?\b(dog|cat|gerbil)\b 

请参阅此正则表达式演示 (或此处的regex101链接 )

您只需要抓取第1组内容:

 var results = Regex.Matches(s, @"(?:\G(?!\A)|^Boy\b).*?\b(dog|cat|gerbil)\b") .Cast() .Select(m => m.Groups[1].Value) .ToList(); 

看到这个C#演示 。

这里,

  • (?:\G(?!\A)|^Boy\b) - 前级匹配的结束( \G(?!\A) )或字符串的开头后跟整个单词Boy
  • .*? - 除了换行符之外的任何0+字符(如果没有将RegexOptions.Singleline传递给Regex构造函数)尽可能少
  • \b(dog|cat|gerbil)\b - 整个单词dogcatgerbil

基本上,这些正则表达式是相似的,尽管\G基于\G的正则表达式可能会更快一些。