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);
}

これに関する問題は、配列内の単語の順序にも依存しますが、禁止されている単語の1つが置換に影響を与えるかどうかです(<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>しましたが、置き換えに成功しませんでした。

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

一般的な場合、ここで必要なのは、これまでに作成された出力ではなく、入力の一部の用語を置き換えることです。これを手動で行うのはそれほど難しいことではありませんが、最初に、どの用語を優先して置き換えるかを決定する必要があります。

用語と置換の辞書があり、置換する用語を選択するための戦略は、「入力の先頭に最も近いものを置き換える。同じ位置に多くの用語が現れる場合は、最も長いものを置き換える」としましょう。 。これを行う1つの方法は次のとおりです。

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();
}

実際の動作をご覧ください

もちろん、これはあなたがここでやりたいことではありません(実際、一度にすべてを1つの正規表現に置き換えるのがおそらく最も便利です)が、それがどのように機能するかを見ることができます

于 2013-02-18T15:23:08.090 に答える