【问题标题】:Counting individual words in a text file计算文本文件中的单个单词
【发布时间】:2011-05-29 23:00:49
【问题描述】:

我正在尝试计算特定单词在文本文件中出现的次数。文本文件作为 perl 程序的程序参数给出。

while($text = <>)
{
    @words = split (/\W*\s+\W*/, $text);
    @words = grep (/^[a-zA-Z\-]+$/, @words);
    foreach $word (@words)
    {
        $wordCount{$word}++;
    }
}

我对这几行不是很清楚-

@words = split (/\W*\s+\W*/, $text);
@words = grep (/^[a-zA-Z\-]+$/, @words);

我知道split 会将字符串拆分为数组变量,但如何拆分?是否如非言词?我不明白 split 函数中使用的正则表达式。

grep 做了什么,我也不清楚它的正则表达式。

附:当我检查这个时,代码似乎有一个错误,如果我输入一个文本文件,其文本为 -

快速的棕色狐狸跳过 懒狗 dog.rose 是棕色,紫色 跳过狐狸。

它只计算了foxdog这两个词,这是不正确的。

这里有什么问题?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    我不确定拆分成一个数组是最节省内存的方法,尤其是对于非常大的文本。如果您有一个几兆字节的文本文件,您将构建一个非常大的数组,这将占用大量内存。

    相反,我会这样做:

    while ($text = <>) {
        while ($text =~ /([A-Za-z\-]+)/g)  {
            my $word = lc($1);    # dont diffrentiate between 'Dog' and 'dog'
            $count++;             # total word count
            $wordCount{$word}++;  # individual word count
        }
    }
    

    然后添加新字符也很容易,如果您碰巧找到任何您希望在单词中包含为有效字符的字符。 IE。如果您认为this_file 可以接受,请将字符更改为[A-Za-z\-_]

    至于你的问题:

    正则表达式\W*\s+W* 的意思是:将一个非单词字符匹配0 到任意次数,后跟1 匹配任意数量的空格,再匹配0 匹配任意数量的非单词字符。一种相当奇怪的拆分方式,但它基本上会围绕所有空格进行拆分,并在此过程中删除所有非单词字符,以获得更正确的单个单词计数。 (例如,它不会将 dog,dog 视为两个不同的词)。

    grep 本身将返回与正则表达式匹配的值列表。正则表达式将匹配@words 中仅由(从头到尾)字母、大写或小写字母和连字符组成的任何数组值。如果值内有任何其他字符,则 grep 将排除它。

    错误是"dog.rose""fox." 不会正确拆分,因为没有空格。因此它们不会被隐式清除非单词字符,因此将使用grep. 删除

    【讨论】:

      【解决方案2】:

      与这些问题一样,有上百万种不同的方式来定义“词”是什么。在这里使用现有的(允许带有内部破折号的字母序列),但使其适用于两个指出的失败案例:

      my $text = 'the quick brown fox jumps over the lazy dog dog.rose is brown, violet jumps the fox.';
      my %wordCount;
      for my $word ( $text =~ /([a-zA-Z]+|-(?=[a-zA-Z\-])(?<=[a-zA-Z\-]-))+/g ) {
          ++$wordCount{$word};
      }
      
      for my $word ( sort { $wordCount{$a} <=> $wordCount{$b} || $a cmp $b } keys %wordCount ) {
           print "$word: $wordCount{$word}\n" 
      }
      

      【讨论】:

      • 不过,您需要区分“Dog”和“dog”。
      【解决方案3】:
      \W is matching word characters
      \s is matching whitespace
      

      正如您可能已经猜到的那样,它不起作用,因为 dog.rose 中的单词之间没有空格。

      我会在 \b 上拆分(这意味着单词边界)。这应该比你的 \W*\s+\W* 更简单、更正确。

      while($text = <>)
      {
          @words = split (/\b/, $text);
          foreach $word (@words)
          {
              $wordCount{$word}++;
          }
      }
      

      【讨论】:

      • @cellcortex:我相信 \W 字符类实际上匹配任何非单词字符。如有错误请指正。
      • \W 是非单词字符,\w 是单词字符
      • \b 如果单词可能包含 - 将不起作用,这显然是其余代码的情况
      • 边界的问题是它也会在' 上分裂,就像“it's”会变成“it”和“s”。最初使用的正则表达式非常聪明。它适用于空白,也适用于其他情况。
      • @ysth:正确。一个带有连字符'-'的单词,即使连字符也算作一个单词。但除此之外,/\b/ 解决了我之前的问题。
      猜你喜欢
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多