捕获组,每行许多组

时间:2013-06-06 16:16:27

标签: c# regex

我有一些带有'控制序列'的html,我已经从内容中删除了html标签,现在我想将'控制序列'变成'样式'。

删除html标签后我就有了......

"<!C43!><!TG!>Some Characters"

最终产生这个...

<span class="C43 TG">Some Characters</span>

到目前为止我的错误c#:

Regex reg = new Regex("<!([^<>]+?)!>");

Match matches = reg.Match(line);
foreach (Group group in matches.Groups)
{
    // finds both groups,
    // and remove the control sequence
}

我的'foreach'还没有多少,因为当我用breakboint检查它时,它会错误地返回以下组...

Group 1 : <!C43!>
Group 2 : C43
<it does not find second group :( >

任何帮助都会受到赞赏,但我主要是寻找正确的正则表达式来找到我在字符串中寻找的内容,但我对正则表达式库也没用,所以最有效的'查找组,商店组,从字符串中删除组我正在搜索'也将非常感激。

3 个答案:

答案 0 :(得分:3)

你正在循环错误的事情。试试这个:

string line = ...;
Regex reg = ...;
for (var match = reg.Match(line); match.Success; match = match.NextMatch())
{
    // in here, don't bother with .Groups... you don't need it
}

答案 1 :(得分:2)

正如其他人所说,由于您的模式只有一个组,因此您希望循环Match而不是Group s。通常的方法是Michael Gunter的for循环或简单地

Match m = reg.Match(line);
while(m.Success)
{
    // read class from m.Groups[1]
    m = m.NextMatch();
}

然而,为了解决你的最终问题,单独取出所有数据并将字符串重新组合在一起可能会有点烦人 - 特别是如果你想一次在多行中进行这种替换。

因此,您可能希望查看Regex.Replace(采用回调的版本)。这样,您就可以在一次匹配中匹配所有内容,然后利用.NET的独特功能访问单个组的多个捕获。

var line = "<!C43!><!TG!>Some Characters";

MatchEvaluator evaluator = new MatchEvaluator(ReplaceCallback);

string output = Regex.Replace(
    line,
    @"(?:<!([^<>]+)!>)+(.+)",
    evaluator
);

你班上的其他地方:

static string ReplaceCallback(Match match)
{
    var sb = new StringBuilder("<span class=\"");
    sb.Append(match.Groups[1].Captures[0].Value);
    for(int i = 1; i < match.Groups[1].Captures.Count; i++)
    {
        sb.Append(" ");
        sb.Append(match.Groups[1].Captures[i].Value);
    }
    sb.Append("\">");
    sb.Append(match.Groups[2].Value);
    sb.Append("</span>");
    return sb.ToString();
}

使用String.Format设置字符串可能会更容易,但我找不到String.Join CaptureCollection的方法。

那么这基本上是做什么的:

模式@"(?:<!([^<>]+)!>)+(.+)"匹配一个或多个<!...!>“标记”,然后是该行的其余部分。这样做时它会捕获<!...!>的内容。在每次重复时,都会记录另一次捕获,您可以在回调中稍后访问它们。在<!...!>令牌之后,我们匹配并使用(.+)捕获该行的其余部分。请注意字符串前面的@:它会逐字地生成字符串,在指定正则表达式模式时应始终这样做 - 否则在转义时会遇到问题。另请注意第一个左括号后的?:。这是为了抑制捕获,因为我们不需要另外包含分隔符<!!>的捕获。除非您确实需要捕获,否则始终使用非捕获组也是一种很好的做法。

然后为输入中的每个匹配调用回调函数。只有一个匹配包含整行。该匹配已捕获组1中的两个令牌以及组2中的其余行。

因此,我们现在可以简单地构建一个以<span ="开头的字符串,然后是一个以空格分隔的列表,其中列出了1组的所有捕获,然后是">,然后是捕获的剩余部分该行,最后是结束</span>

正如我所说,如果你找到了String.Join收集组的方法,回调函数会减少到三行左右。

如果MatchGroupCapture之间的区别对您来说仍然有点模糊,我建议在回调函数中设置一个断点,然后检查match对象那里。

答案 2 :(得分:0)

我无法在RegexHero中重现您的问题:

http://www.regexhero.net/tester

它将两组捕获为:

1: C43
1: TG

您确定您的输入是您所期望的吗?您是否在结果的预期集合上进行迭代?