4

我想做的是某种“禁用词”突出显示。

以下是我的价值观:

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

{ "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"

然后替换为<bafter 将是:

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

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

4

2 回答 2

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);
于 2013-02-18T15:07:03.927 回答
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();
}

看到它在行动

当然,这并不是您想要在这里做的(事实上,用一个正则表达式一次替换所有内容可能是最方便的),但您可以看到它是如何工作的。

于 2013-02-18T15:23:08.090 回答