正则表达式:如何从字符串中获取单词(C#)

时间:2010-01-29 00:17:14

标签: c# regex string replace

我的输入包含用户发布的字符串。

我想要做的是创建一个包含单词的字典,以及它们被使用的频率。 这意味着我想解析一个字符串,删除所有垃圾,并获得一个单词列表作为输出。

例如,输入是 "#@!@LOLOLOL YOU'VE BEEN \***PWN3D*** ! :') !!!1einszwei drei !"

我需要的输出是列表:

  • "LOLOLOL"
  • "YOU'VE"
  • "BEEN"
  • "PWN3D"
  • "einszwei"
  • "drei"

我不是正则表达的英雄,而是Google搜索,但我的Google-kungfu接缝很弱......

我如何从输入转到想要的输出?

6 个答案:

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