代码之家  ›  专栏  ›  技术社区  ›  Led

regex:如何从字符串中获取单词(c)

  •  12
  • Led  · 技术社区  · 14 年前

    我的输入由用户发布的字符串组成。

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

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

    我需要的输出是列表:

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

    我在正则表达式方面不是英雄,一直在谷歌搜索,但我的谷歌功夫很弱…

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

    6 回复  |  直到 7 年前
        1
  •  18
  •   John Gietzen    14 年前

    简单正则表达式:

    \w+

    这与一系列“word”字符匹配。那就是 几乎 你想要什么。

    这一点更准确:

    \w(?<!\d)[\w'-]*

    它匹配任意数量的字字符,确保第一个字符不是数字。

    这是我的火柴:

    1洛洛尔
    2你
    3被
    4 PWN3D
    5爱因斯坦
    6德里

    现在,更像是这样。

    编辑:
    负向查找的原因是一些regex风格支持Unicode字符。使用[a-z a-z]可能会遗漏一些需要的“单词”字符。允许 \w 不允许 \d 包括所有可以在任何文本块中以单词开头的Unicode字符。

    编辑2:
    我发现了一种更简洁的方法来获得负查找的效果:使用一个负排除的双重负字符类。

    [^\W\d][\w'-]*(?<=\w)

    这与上面相同,但它也确保了 末端 带有单词字符。最后,还有:

    [^\W\d](\w|[-']{1,2}(?=\w))*

    确保一行中的非字字符不超过两个。也就是说,它匹配的是“单词向上”而不是“单词向上”,这是有意义的。如果您希望它与“word--up”匹配,而不是“word--up”,则可以更改 2 到A 3 .

        2
  •  5
  •   Mike Atlas    14 年前

    你应该研究自然语言处理(NLP),而不是正则表达式,如果你的目标是一种以上的口语,你也需要考虑到这一点。既然你用的是C,请查看 SharpNLP 项目。

    编辑 :只有当您关心要拆分的单词的语义内容时,此方法才是必要的。

        3
  •  2
  •   Jason    14 年前

    如果你只需要标记化,你不一定需要一个regex。首先,可以通过删除除空格之外的所有非字母字符来清理字符串,然后执行 Split() 关于空间角色。尽管宫缩可能很困难,但这对大多数情况都有效。这至少能让你开始。

        4
  •  2
  •   Greg Bacon    14 年前

    使用以下内容

    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]
        5
  •  0
  •   JSmyth    14 年前

    我的直觉不是使用正则表达式,而是做一两个循环。

    循环访问字符串中的每个字符,如果不是有效的字符,请用空格替换它 然后使用string.split()并在空格上拆分。

    对映体和连字符可能更难确定它们是垃圾字符还是合法字符。但是,如果使用for循环迭代字符串,那么从当前字符向后和向前看应该会有帮助。

    然后你会有一个单词列表-对于每个单词,检查它们在你的字典中是否有效。如果你想快速搜索,最好是执行某种二进制搜索。但是为了让它工作,线性搜索将更容易开始。

    编辑:我只提到字典的事情,因为我认为你可能只对合法的词感兴趣,即不是“asdfasdf”,但如果这不是你需要的话,请忽略最后一句话。

        6
  •  0
  •   user8846868    7 年前

    我为这样的字符串编写了一个扩展名:

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