1

我有一些带有“控制序列”的 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”中还没有太多东西,因为当我用断点检查它时,它错误地返回了以下组......

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

任何帮助将不胜感激,但我主要是在寻找正确的正则表达式以在字符串中找到我要查找的内容,但我对正则表达式库也无用,所以最有效的“查找组,存储组” ,从我正在搜索的字符串中删除组'也将不胜感激。

4

3 回答 3

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
}
于 2013-06-06T16:23:04.450 回答
2

正如其他人所说,您希望循环Matches 而不是Groups 因为您的模式只有一组。执行此操作的常用方法是 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.JoinCaptureCollection

所以这基本上是在做什么:

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

然后为输入中的每个匹配调用回调函数。只有一个匹配包含整行。那场比赛在 group 中捕获了两个令牌,在 group 中捕获1了其余的线2

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

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

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

于 2013-06-06T16:43:44.577 回答
0

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

http://www.regexhero.net/tester

它将 2 组捕获为:

1: C43
1: TG

你确定你的输入是你期望的吗?您是否正在迭代预期的结果集合?

于 2013-06-06T16:22:28.440 回答