正则表达式,用于捕捉字母之间有特殊字符的单词



我是regex的新手,我正在为注释功能(在c#中)编写高级脏话过滤器。为了节省时间,我知道所有的过滤器都可以被愚弄,不管它们有多好,你不必告诉我。我只是想让它比基本的单词替换更高级一点。我已经把这个任务分成了几个不同的方法,这是其中之一。

我需要的是一个特定的正则表达式,它可以捕获如下字符串:

s_h_i_t
s h i t
S<>H<>I<>T
s_/h_/i_/t
s***h***i***t

你懂的。我想我要找的是一个正则表达式,它说"一个或多个字符不是字母数字"。这应该包括空格和您可以在标准(西方)键盘上键入的所有特殊字符。如果可能的话,它还应该包括换行符,这样它就可以捕捉到像

这样的内容。
s
h
i
t

应该始终至少有一个字符存在,以避免可能的误报,例如

Finish it.

这当然意味着像

sh_it

不会被捕获,但正如我所说的,这并不重要,它不必是完美的。我所需要的就是正则表达式,我可以自己拆分单词并插入正则表达式。我有RegexOptions。在我的c#代码中设置IgnoreCase选项,因此实际单词中的字符大小写不是问题。此外,这个正则表达式不应该担心"leetspeek",即单词的一些实际字母被其他字符替换:

sh1t

我有一个不同的方法来处理这个问题。提前感谢您的帮助。

让我们看看这个正则表达式是否适合你:

/w(?:_|W)+/

好吧,哈姆扎的回答起作用了。然而,我在解决方案的工作中遇到了一个编程问题。当我替换单词时,我总是知道单词的长度。所以我知道要用多少个星号来代替它。如果我匹配shit,我知道我需要加4个星号。但是如果我匹配s[^a-z0-9]+h[^a-z0-9]+[^a-z0-9]+i[^a-z0-9]+t,我可能会捕获s#h#i#t或者catch s------h------i--------t。在这两种情况下,匹配文本的长度将与模式的长度相差很大。我怎样才能得到匹配字符串的实际长度?

bs[W_]*h[W_]*i[W_]*t[W_]*(?!w)

  • 匹配非单词字符或字符_或空白字符(也包括新换行符)的字母之间的字符

  • b(字边界)确保Finish it不匹配

  • (?!w)确保sh ituu不匹配,您可能想要删除/修改它,因为s_hittt也不会匹配。bs[W_]*h[W_]*i[W_]*t+[W_]*(?!w)将匹配最后一个重复字符

    的单词
  • 修改bs[W_]*h[W_]*i[W_]*t[W_]*?(?!w)将使最后一个字符类的匹配不贪婪,在sh it&&&中只有sh it将匹配

  • bs[Wd_]*h[Wd_]*i[Wd_]*t+[Wd_]*?(?!w)将匹配sh1i444t(字符之间的数字)

编辑:

(?!w)是一个负的预判。它基本上检查您的匹配是否后跟一个单词字符(单词字符是[a -z09_])。它的长度为0,这意味着它不会被包含在匹配中。如果你想捕捉像"shi*tface"你得把它取下来。(http://www.regular-expressions.info/lookaround.html)

单词边界[/b]匹配单词开始或结束的位置,它的长度为0,这意味着它在字符之间匹配

[W]是一个负字符类,我认为它等于[^a- za - z0 -9_]或[^ W]

您希望匹配每个字母由相同的非单词字符分隔的单词。

可以使用

bp{L}(?=([W_]+))(?:1p{L})+b

参见regex演示。(我添加了(?!n)以使regex为每行工作,就好像它是一个单独的字符串一样)详细信息:

  • b -字边界
  • p{L} -一个字母
  • (?=([W_]+)) -一个正向前看,匹配紧跟着任何非单词或_字符的位置(捕获到组1)
  • (?:1p{L})+ -捕获到组1和字母的相同字符序列的一个或多个重复
  • b -字边界。

要检查字符串中是否存在这样的模式,可以使用

var HasSpamWords = Regex.IsMatch(text, @"bp{L}(?=([W_]+))(?:1p{L})+b");

要返回字符串中出现的所有内容,可以使用

var results = Regex.Matches(text, @"bp{L}(?=([W_]+))(?:1p{L})+b")
    .Cast<Match>()
    .Select(x => x.Value)
    .ToList();

参见c#演示。

如果您获得Match.Length并使用.Select(x => x.Length),则获取每个字符串的长度很容易。如果您需要获取删除所有特殊字符的字符串长度,只需使用.Select(x => x.Value.Count(c => char.IsLetter(c)))(参见此c#演示)。

最新更新