在 C# 中使用 .matches .Concat 进行正则表达式和正确捕获

Regex and proper capture using .matches .Concat in C#

我有以下正则表达式:

@"{thing:(?:((\w)*)([^}]*?))+}"

我正在使用它来查找字符串中的匹配项:

MatchCollection matches = regex.Matches(string);
       IEnumerable formatTokens = matches[0].Groups[3].Captures
                                   .OfType<Capture>()
                                   .Where(i => i.Length > 0)
                                   .Select(i => i.Value)
                                   .Concat(matches[0].Groups[1].Captures.OfType<Capture>().Select(i => i.Value));

这曾经产生我想要的结果;但是,此后我的目标发生了变化。这是现在所需的行为:

假设输入的字符串是'stuff/{thing:aa/bb/cccc}{thing:cccc}'

希望 formatTokens 为:

formatTokens[0] == "aa/bb/cccc"
formatTokens[1] == "cccc"

现在,这是我得到的:

formatTokens[0] == "/"
formatTokens[1] == "/"
formatTokens[2] == "cccc"
formatTokens[3] == "bb"
formatTokens[4] == "aa"

请特别注意 "cccc" 即使输入了两次也不会出现两次。

我认为问题是 1) 正则表达式中的重新捕获和 2) concat 配置(这是我希望将所有内容分开时的配置),但到目前为止我还没有找到能够产生什么的组合我想。有人可以阐明正确的 regex/concat 组合以产生上述预期结果吗?

Mod更新

我不确定你为什么选择 Stringnuts 正则表达式,因为它匹配
大括号 {} 内的任何内容。

SO 上的温顺得不到深刻知识的满足,
所以这可能是你真正的问题。

让我们分析您的正则表达式。

 {thing:
 (?:
      (                             # (1 start)
           ( \w )                        # (2)
           * 
      )                             # (1 end)
      ( [^}]*? )                    # (3)
 )+
 }

这减少到这个

 {thing:
 (?: \w [^}]*? )+
 }

唯一的限制是 {thing: 之后必须有一个词。
之后可以有其他任何东西,因为这个子句 [^}]*? 接受
任何东西。
此外,即使该子句不贪心,周围的集群也只会 运行 一次迭代 (?: )+

所以,基本上,除了单个单词要求外,它几乎什么都不做。

您的正则表达式可用于 as is 以获得复杂的匹配,
并且因为您已经捕获了 Capture Collections,
中的所有部分 对于每场比赛,您可以使用下面的代码将其拼凑在一起。

我会尝试更好地理解正则表达式,然后再继续其他内容,因为它可能比
用于提取数据的语言技巧。

下面是如何使用 未更改的 正则表达式将它们拼凑在一起。

Regex regex = new Regex(@"{thing:(?:((\w)*)([^}]*?))+}");
string str = "stuff/{thing:aa/bb/cccc}{thing:cccc}";
foreach (Match match in regex.Matches(str))
{
    CaptureCollection cc1 = match.Groups[1].Captures;
    CaptureCollection cc3 = match.Groups[3].Captures;
    string token = "";
    for (int i = 0; i < cc1.Count; i++)
        token += cc1[i].Value + cc3[i].Value;
    Console.WriteLine("{0}", token);
}

输出

aa/bb/cccc
cccc

请注意,例如,您的正则表达式几乎可以匹配里面的所有内容
大括号只要第一个字符是一个单词。

例如匹配{thing:Z,,,*()(((asgassgasg,asgfasgafg\/\=99.239 }

您可能需要考虑实际允许的要求
在牙套里面。

祝你好运!

您可以使用

Regex.Matches(s, @"{thing:([^}]*)}")
    .Cast<Match>()
    .Select(x => x.Groups[1].Value)
    .ToList()

regex demo

详情

  • {thing: - 文字 {thing: 子串
  • ([^}]*) - 捕获第 1 组(当获得匹配项时,可以通过 match.Groups[1].Value 访问其值):除 }
  • 之外的 0+ 个字符
  • } - 一个 } 字符。

通过这种方式,您可以找到多个匹配项,并且只收集结果 list/array 中的第 1 组值。