我有一个应用程序,我的用户可以写评论。 但我希望过滤侮辱特殊字符。
string comment = "Ðick"; // With special "Ð".
comment = Regex.Replace(comment, @"[^a-z0-9 ]", "[a-z]"); // Replace special char by "[a-z]"
Regex regex = new Regex(@""+comment +""); // @"[a-z]ick"
return (regex.IsMatch("dick")) ? true : false;
当注释只是“Ðick”时,该函数返回true,但如果注释为“Ðickwith another word”,则该函数返回false。为什么呢?
答案 0 :(得分:2)
你要做的事情往往是通过Canonical分解加上剥离"组合变音符号"来完成的。您无法使用纯正则表达式执行此操作...即使只有少量C#,您也必须手动为某些字符执行此操作(例如Ð
到D
或Ø
到O
)。对于其他一些角色,您可以使用更多"自动化"使用è
的方式(例如e
到string.Normalize
),例如:
string comment = "Ðè";
// Here we split (è) to U+0065 (e) U+0300 (̀)
string commentNormalized = comment.Normalize(NormalizationForm.FormD);
// Here we remove all the UnicodeCategory.NonSpacingMark
// that are the diacritics like U+0300 (̀)
// and rebuild the string. This line can be speedup a little, but
// it would be longer to write :-)
string comment2 = new string(commentNormalized.Where(x => char.GetUnicodeCategory(x) != UnicodeCategory.NonSpacingMark).ToArray());
现在comment2
是"Ðe"
。
这是因为è有一个" Canonical分解" U+0065 (e) U+0300 (̀)
,因此您可以发现è
是"类似的"至e
,而对于Ð它是" Canonical分解"仍然是U+00D0 (Ð)
所以相同的角色。
你要做的事情是徒劳的:当你禁用一个角色时,用户会找到另一个类似的"你听说过Leet吗? D1ck
(1
而不是i
)比你的话更好吗? : - )
通常情况下,拥有一个包含Dork
和Ðork
的禁止字词"的字典通常会更好,并且当您找到"的新排列时,通常会更好。进攻"单词,你只需添加它。人类的幻想是无限的...所以你的字典必须是:-)但是一次一个字。