我的输入包含用户发布的字符串。
我想要做的是创建一个包含单词的字典,以及它们被使用的频率。 这意味着我想解析一个字符串,删除所有垃圾,并获得一个单词列表作为输出。
例如,输入是
"#@!@LOLOLOL YOU'VE BEEN \***PWN3D*** ! :') !!!1einszwei drei !"
我需要的输出是列表:
"LOLOLOL"
"YOU'VE"
"BEEN"
"PWN3D"
"einszwei"
"drei"
我不是正则表达的英雄,而是Google搜索,但我的Google-kungfu接缝很弱......
我如何从输入转到想要的输出?
答案 0 :(得分:18)
简单正则表达式:
\w+
这匹配一串“单词”字符。那就是几乎你想要的东西。
这稍微准确一些:
\w(?<!\d)[\w'-]*
它匹配任意数量的单词字符,确保第一个字符不是数字。
以下是我的比赛:
1 LOLOLOL
2你有 3 BEEN
4 PWN3D
5 einszwei
6 drei
现在,这更像是它。
修改强>
负面后瞻的原因是一些正则表达式支持Unicode字符。使用[a-zA-Z]会错过很多可取的“单词”字符。允许\w
和禁止\d
包括可以在任何文本块中启动单词的所有Unicode字符。
编辑2:
我找到了一种更简洁的方法来获得负面的后观效果:双重负面角色类,只有一个负面排除。
[^\W\d][\w'-]*(?<=\w)
这与上述相同,只是它还确保单词以结尾。最后,有:
[^\W\d](\w|[-']{1,2}(?=\w))*
确保一行中不超过两个非单词字符。 Aka,它匹配“word-up”而不是“word-up”,这是有道理的。如果您希望它匹配“word-up”,而不是“word --- up”,则可以将2
更改为3
。
答案 1 :(得分:5)
您应该研究自然语言处理(NLP),而不是正则表达式,如果您要定位多种口语,您也需要将其考虑在内。由于您使用的是C#,请查看SharpNLP项目。
编辑:只有当您关心要分割的单词的语义内容时,才需要使用此方法。
答案 2 :(得分:2)
如果您正在进行令牌化,那么您不一定需要正则表达式。首先,您可以通过删除除空格之外的所有非字母字符来清理字符串,然后在空格字符上执行Split()
。这对大多数事情都有效,尽管收缩可能很困难。这至少应该让你开始。
答案 3 :(得分:2)
使用以下
var pattern = new Regex(
@"( [^\W_\d] # starting with a letter
# followed by a run of either...
( [^\W_\d] | # more letters or
[-'\d](?=[^\W_\d]) # ', -, or digit followed by a letter
)*
[^\W_\d] # and finishing with a letter
)",
RegexOptions.IgnorePatternWhitespace);
var input = "#@!@LOLOLOL YOU'VE BEEN *PWN3D* ! :') !!!1einszwei drei foo--bar!";
foreach (Match m in pattern.Matches(input))
Console.WriteLine("[{0}]", m.Groups[1].Value);
产生
的输出[LOLOLOL] [YOU'VE] [BEEN] [PWN3D] [einszwei] [drei] [foo] [bar]
答案 4 :(得分:0)
我的直觉不是使用正则表达式,而只是做一两圈。
迭代字符串中的每个字符,如果不是有效字符,则用空格替换它 然后使用String.Split()并拆分空格。
确定它们是垃圾字符还是合法字符时,相比和连字符可能会有点棘手。但是如果你使用for循环迭代字符串,那么从当前字符向后和向前查看应该对你有所帮助。
然后你会得到一个单词列表 - 对于每个单词,检查它们是否在你的字典中有效。如果你想要快速,那么执行一些二进制搜索将是最好的。但只是为了使其工作线性搜索将更容易开始。
编辑:我只提到字典的事情,因为我认为你可能只对合法的词感兴趣,即不是“asdfasdf”,但如果那不是你需要的话,就忽略那句话。答案 5 :(得分:0)
我为此写了一个String的扩展名:
private static string[] GetWords(string text)
{
List<string> lstreturn = new List<string>();
List<string> lst = text.Split(new[] { ' ' }).ToList();
foreach (string str in lst)
{
if (str.Trim() == "")
{
lstreturn.Add(str);
}
}
return lstreturn.ToArray();
}