使用Regex转换字符串

时间:2012-06-05 17:58:31

标签: c# regex string parsing

我有一些我需要使用C#修改的HTML内容。它在概念上很简单,但我不确定如何有效地做到这一点。内容包含多个分隔数字后跟一个空锚标记。我需要使用分隔数字并将其插入到锚标记中的javascript函数调用中。 E.G。

源字符串将包含以下内容:

%%1%%<a href="#"></a> 
<p>A bunch of HTML markup</p>

%%2%%<a href="#"></a>
<p>Some more HTML markup</p>

我需要将其转换为:

<a href="#" onclick="DoSomething('1')></a> 
<p>A bunch of HTML markup</p>

<a href="#" onclick="DoSomething('2')></a>
<p>Some more HTML markup</p>

%% \ d + %%次数没有限制。我写了一个正则表达式,希望我可以使用Replace方法,但我不确定是否可以使用每个组的多个实例。这就是我所拥有的:

%%(?<LinkID>\d+)%%(?<LinkStart><a[\s\S]*?)(?:(?<LinkEnd>>[\s\S]*?)(?=%%\d+|$))

// %%(?<LinkID>\d+)%%        Match a number surrounded by %% and put the number in a group named LinkID
// (?<LinkStart><a[\s\S]*?)  Match <a followed by any characters until next match (non greedy), in a group named LinkStart
// (?:                       Logical grouping that does not get captured
// (?<LinkEnd>>[\s\S]*?)     Match > followed by any characters until next match, in a group named LinkEnd
// (?=%%\d+%%|$)             Where the former LinkEnd group is followed by another instance of a delimited number or the end of the string. (I don't think this is working as I intended.)

也许可以使用一对Regex操作和String.Format的某种组合。我在正则表达方面的表现并不是那么好,所以请稍微贬低你的答案。

4 个答案:

答案 0 :(得分:1)

使用正则表达式解析HTML已在SO上广泛讨论。 The consensus is that it should not be done

如果您需要解析HTML,我建议您使用HTML Agility Pack之类的内容。这允许您使用类似于xPath的内容来标识您要使用的HTML。

答案 1 :(得分:1)

我会说你的正则表达式几乎就是你想要的 - 我稍微改了一下。如果$仅匹配字符串的末尾,则可以使用此方法:

%%(\d+)%%(<a[^>]*)(></a>)(.*?)(?=%%\d|$)

如果你决定使用它,那么对于每个匹配你都可以访问组,这样你就可以构造新的字符串 - 这可能比替换现有字符串中的东西更容易。

答案 2 :(得分:0)

我会将string.split用于此。

string emptyAnchor = "<a href=""#""></a>";
string src = GetData();
string[] splits = src.split(new string[]{"%%"}, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();

//first entry is blank, set to 1
int i = 1;
while(i < splits.length)
{
    string id = splits[i];
    //increment for data string
    i++;
    //prehaps use a StringReplaceFirstOccurrence function instead
    sb.Append(splits[i].Replace(emptyAnchor, GetDataFromID(id)));
    i++;
}
string output = sb.ToString();

答案 3 :(得分:0)

原来Regex.Replace已经足够智能来处理多个匹配。我只是修改了我的正则表达式而不是使用前瞻。我的想法是在%%分隔符中找到数字并将其添加到一个组中,找到下一个锚标记内的内容并将其添加到一个组中,然后将整个匹配替换为具有在该组中捕获的文本的新版本。两组插入其中。替换方法似乎在没有任何其他帮助的情况下自动正确处理后续匹配。

string originalText = "<h3>%%1%%<a href=\"#\">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>" +
                            "<h3>%%2%%<a href=\"#\">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p>" +
                            "<p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>";

Regex regex = new Regex(@"%%(\d+)%%[\s]*<a[\s\S]*?>([\s\S]*?)</a>");
string result = regex.Replace(originalText, "<a href=\"#\" onclick=\"DoSomething($1)\">$2</a>");
Debug.WriteLine("Original Text: \"" + originalText + "\"");
Debug.WriteLine("Result Text: \"" + result + "\"");

输出:

Original Text: "<h3>%%1%%<a href="#">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p><h3>%%2%%<a href="#">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p><p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>"

Result Text: "<h3><a href="#" onclick="DoSomething(1)">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p><h3><a href="#" onclick="DoSomething(2)">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p><p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>"