替换正则表达式匹配中

时间:2016-04-08 19:39:42

标签: c# regex

编辑:此示例使用html,但我需要这种类型的方案来处理其他类型的字符串。请将其视为正则表达式问题,而不是HTML问题。

我们说我有一个这样的字符串:

<h1>Hello</h1><h2>World</h2><h3>!</h3>

我可能需要将文字替换为任何其中一个标题标记,但让我们使用此示例,我只想将<h2>修改为如下所示:

<h1>Hello</h1><div id="h2div"></div><h2>World</h2><h3>!</h3>

由于我可能需要替换任何标题,因此我只使用正则表达式搜索<h*。现在,我希望我的代码能够说出您找到的所有<h*个代码,只替换第二个代码&#34;。

我以为我找到了答案: How do I replace a specific occurrence of a string in a string?

不幸的是,结果并不是我想要的。这是我的示例代码:

    private void button1_Click(object sender, EventArgs e)
    {
        //sample html file string:
        var htmlText = "<h1>Hello</h1><h2>World</h2><h3>!</h3>";

        //this text should replace <h2 with <div id="h2div"></div><h2"
        var replacementString = "<div id=\"" + "h2div" + "\"" + "</div>" + "<h2";
        int replacementIndex = 1; //only replace the second occurence found by regex.

        //find ALL occurrences of <h1 through <h6 in the file, but only replace <h2.
        htmlText = Regex.Replace(htmlText, "<h([1-6])", m => replacementString + replacementIndex++);

    }

我是否指定replacementIndexreplacementIndex++并不重要,这是有道理的,但我只想尽可能地将代码与我找到的答案进行匹配。

输出如下:

<div id="h2div"></div><h21>Hello</h1><div id="h2div"></div><h22>World</h2><div id="h2div"></div><h23>!</h3>

这里不应该发生很多事情。首先,应该只创建一个<div>标记,而不是三个。其次,<h标记仅替换为<h2,因此现在我们最终得到<h21<h22<h23

从几个月前开始,我在理解正则表达式匹配方面变得越来越好,但我对正则表达式的数学评估和组合并不熟悉;我想这就是我可能需要的东西。

您能否推荐我如何修复代码,以便替换正则表达式匹配的特定索引?

3 个答案:

答案 0 :(得分:0)

抱歉无法用C#回答,但答案应该非常相似。对于您的特定情况,JavaScript String.prototype.replace()的regexp属性为/(<h1.+?\/h1>)/,替换属性为"$1<div id="h2div">"所以;

var str = "<h1>Hello</h1><h2>World</h2><h3>!</h3>",
 repStr = str.replace(/(<h1.+?\/h1>)/,'$1<div id="h2div"></div>');

console.log(repStr) // "<h1>Hello</h1><div id="h2div"></div><h2>World</h2><h3>!</h3>"

或者,如果您不想使用捕获组,您仍然可以使用

var repStr = str.replace(/<h1.+?\/h1>/,'$&<div id="h2div"></div>');

在这种特定情况下基本上会得到相同的结果。

答案 1 :(得分:0)

使用MatchEvaluator?

private static int count = 0;
    static string CapText(Match m)
    {
        count++;

        if (count == 2)
        {
            return "<div id=\"h2div\"></div>" + m.Value;
        }

        return m.Value;
    }

private void button1_Click()
{
    var htmlText = "<h1>Hello</h1><h2>World</h2><h3>!</h3>";
    Regex rx = new Regex(@"<h([1-6])");
    var result = rx.Replace(htmlText, new MatchEvaluator(ClassOfThis.CapText));
}

答案 2 :(得分:0)

我为此忙碌了整整一天。当然,提出这个问题有时会让创意变得流动,所以这就是我提出的解决方案。它使用MatchCollection,然后使用字符串构建器插入字符串。字符串生成器可能有点过分,但它可以工作: - )

replacementIndex定义要插入文本的匹配项。在我的例子中,正则表达式找到三个实例并修改找到的索引1.从那里,我得到起始字符串索引并使用子字符串插入文本。这只是来自按钮的测试代码,用于证明功能。

    private void button1_Click(object sender, EventArgs e)
    {
        //sample text.
        var htmlText = "<h1>Hello</h1><h2>World</h2><h3>!</h3>";

        //the string builder will handle replacing the text.
        var stringBuilder = new StringBuilder(htmlText);

        //build the replacement text.
        var replacementString = "<div id=\"" + "h2div" + "\">" + "</div>";
        int replacementIndex = 1; //only replace the second occurence found by regex (zero-indexed).

        //find ALL occurrences of <h1 through <h6 in the file, but only replace <h2.
        var pattern = "<h([1-6])";
        MatchCollection matches = Regex.Matches(htmlText, pattern); //get all the matches.
        int startIndex = matches[replacementIndex].Index; //get the starting string index for the match.

        //insert the required text just before the found match.
        stringBuilder.Insert(startIndex, replacementString);

        //copy text to clipboard and display it on screen.
        htmlText = stringBuilder.ToString();
        System.Windows.Forms.Clipboard.SetText(htmlText);
        MessageBox.Show(htmlText);
    }