查找并替换多个单词,而不会影响将来的替换

时间:2013-02-18 14:51:10

标签: c#

我想要做的是某种被禁止的词语"高亮。

以下是我的价值观:

我有一个数组中的禁止词列表

{ "word1", "word2", "word3", "word4" }

我有一个代表评论的字符串

"i want to word1ban this word3 stupidword4 comment"

我想在html粗体标签(<b> </b>)中突出显示这些内容。 因此,例如,此注释字符串将变为:

"i want to <b>word1</b>ban this <b>word3</b> stupid<b>word4</b> comment"

我实际上这样做的方式是使用正则表达式替换它并且它工作得非常好,除了一件让我讨厌的事情。

foreach (var word in words)
{
    value = Regex.Replace(value, string.Format(@"{0}", Regex.Escape(HttpUtility.HtmlEncode(word))), "<b>" + word + "</b>", RegexOptions.IgnoreCase);
}

这个问题,也取决于数组中单词的顺序,是否有一个被禁止的单词会影响你的替换(<b></b>

例如,如果您将此添加到禁止的字词:<b

在代码之后,第一个迭代结果将是:

"i want to <b>word1</b>ban this <b>word3</b> stupid<b>word4</b> comment"

然后用<b替换它:

"i want to <b><b</b>>word1</b>ban this <b><b</b>>word3</b> stupid<b><b</b>>word4</b> comment"

我不想影响我的替代品。我想知道我们怎么做到这一点。我尝试在我的正则表达式中添加例外,以便在替换中排除<b></b>但没有成功。

2 个答案:

答案 0 :(得分:2)

忽略问题的整个“HTML”方面,并从

的角度来看它
  

我想找到并替换几个单词,但我不想要替换我以后影响未来的替换

你可以做一件事:立即进行所有替换!

var pattern = "(" + String.Join("|", words.Select(w => Regex.Escape(w))) + ")";
// e.g. (word1|word2|word3|word4)
value = Regex.Replace(
    value,
    pattern,
    "<b>$1</b>",
    RegexOptions.IgnoreCase);

答案 1 :(得分:0)

在一般情况下,您需要的是在输入中替换某些术语,而不是在目前为止生成的输出中替换。这不是很难手动完成,但首先你必须确定哪个术语优先被替换。

假设您有一个术语和替换字典,选择要替换的术语的策略是“替换最接近输入开头的术语;如果许多术语出现在同一位置,请替换最长的一个“。这是一种方法:

string ReplaceWithoutOverlap(string input, IDictionary<string, string> replacements)
{
    var processedCharCount = 0;
    var sb = new StringBuilder();
    while (processedCharCount < input.Length) {
        var replacement = replacements
                .Select(r => Tuple.Create(r.Key, input.IndexOf(r.Key, processedCharCount)))
                .Where(t => t.Item2 != -1)
                .OrderBy(t => t.Item2)
                .ThenByDescending(t => t.Item1.Length)
                .FirstOrDefault();

        if (replacement == null)
        {
            break;
        }

        sb.Append(input, processedCharCount, replacement.Item2 - processedCharCount);
        sb.Append(replacements[replacement.Item1]);
        processedCharCount = replacement.Item2 + replacement.Item1.Length;
    }

    sb.Append(input.Substring(processedCharCount));
    return sb.ToString();
}

<强> See it in action

当然这不是完全你想在这里做什么(实际上用一个正则表达式替换所有东西可能是最方便的),但是你可以看到它是如何工作的。