在C#

时间:2018-06-19 23:28:41

标签: c# regex match regex-group

我有以下正则表达式:

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

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

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组合以产生上述预期结果吗?

2 个答案:

答案 0 :(得分:2)

您可以使用

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

请参见regex demo

详细信息

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

这样,您会找到多个匹配项,并且仅在结果列表/数组中收集第1组值。

答案 1 :(得分:0)

模块更新

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

对SO的温顺将无法获得深度知识的满足,
所以这可能是您真正的问题。

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

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

这就是这个

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

唯一的限制是{thing:之后必须有一个单词。
之后,还有其他任何事情,因为此条款[^}]*?接受
任何东西。
另外,即使该子句不是贪婪的,周围的簇也只会运行一次迭代(?: )+

因此,基本上,除了单词要求之外,它几乎不执行任何操作。

您的正则表达式可用于 as is 来获得复杂的匹配,
并且因为您已经捕获了捕获集合中的所有部分,所以
每场比赛,您都可以使用以下代码将它们拼凑起来。

在继续学习其他内容之前,我会尝试更好地理解正则表达式,因为它可能比
重要得多。 用于提取数据的语言技巧。

以下是使用未更改正则表达式将所有内容组合在一起的方法。

Regex regex = new Regex(@"{thing:(?:((\w)\2*)([^}]*?))+}");
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 }

您可能要考虑实际允许的要求
大括号内。

祝你好运!