C# 查找具有额外资格标准的所有匹配项

C# 查找具有额外资格标准的所有匹配项,c#,regex,C#,Regex,给出如下句子: 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(第三句将返回不受欢迎的“cat”)

给出如下句子:

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(第三句将返回不受欢迎的“cat”)

整个短语直到最后一个匹配的动物,例如“男孩有一只狗和一只猫”,而第一组也是唯一一组是“猫”


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

您可以使用积极的回顾:

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

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

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

您只需抓取第1组内容:

var results = Regex.Matches(s, @"(?:\G(?!\A)|^Boy\b).*?\b(dog|cat|gerbil)\b")
            .Cast<Match>()
            .Select(m => m.Groups[1].Value)
            .ToList();
var results=Regex.Matches(s,@“(?:\G(?!\A)^ Boy\b.*?\b(狗|猫|沙鼠)\b”)
.Cast()
.Select(m=>m.Groups[1]。值)
.ToList();

这里,

  • (?:\G(?!\A)^Boy\b)
    -前一个匹配的结尾(
    \G(?!\A)
    )或字符串的开头,后跟整个单词
    Boy
  • *?
    -除换行符以外的任何0+字符(如果没有
    RegexOptions。将单行
    传递给
    Regex
    构造函数)尽可能少
  • \b(狗|猫|沙鼠)\b
    -一个完整的单词
    沙鼠

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

这是否需要解释像
男孩没有沙鼠但有猫这样的事情?那可能会很棘手,不。如果是从男孩开始的话,我希望所有的动物都在那句话里。无论是比赛还是团体,我都不在乎,我只需要动物一个人,在所有以“男孩”开头的短语中。编辑问题以消除歧义。只需使用
(?可能应该确保
^Boy\b
,尽管第一个词可能是
抵制
@ctwheels是的,那应该是第二个建议。@n00b还有另一个选择-
(?:\G(?)\A)|^Boy\b.*?\b(狗|猫|沙鼠)
和抓
m.Groups[1].Value
。是否可以通过分组而不是匹配来完成相同的最终目标(即第一句话将第一组返回为“dog”,第二组返回为“cat”)?@n00b否,因为在模式+1中捕获组的组数与
(…)
的组数相同(整个匹配在第0组中)。您可以通过
捕获
访问它们,但我认为这是不合理的。您还有什么其他要求?
var results = Regex.Matches(s, @"(?<=^Boy\b.*?)\b(?:dog|cat|gerbil)\b")
        .Cast<Match>()
        .Select(m => m.Value)
        .ToList();
var strs = new List<string>() { "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<Match>()
            .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!
------
(?:\G(?!\A)|^Boy\b).*?\b(dog|cat|gerbil)\b
var results = Regex.Matches(s, @"(?:\G(?!\A)|^Boy\b).*?\b(dog|cat|gerbil)\b")
            .Cast<Match>()
            .Select(m => m.Groups[1].Value)
            .ToList();