在bash中为词频添加序数排名

时间:2017-10-05 17:26:11

标签: bash shell awk

与此问题类似How to create a frequency list of every word in a file?

我想为具有不同输出的单词创建频率表。我没有单词和它的频率,而是希望得到单词的排名。因此,最常见的单词是数字1,第二个较少的单词是2,依此类推。具有相同频率的单词应具有相同的排名。

我尝试了解awk语法或其他建议,但我没有管理。

输入文本文件示例:

ora
remo
ora
ora
hello
tr
tr
tr
remo
rand
rand
rand
hello

输出应如下所示:

tr 1
rand 1
ora 1
remo 2
hello 2

3 个答案:

答案 0 :(得分:3)

根据您的预期输出:

sort file|uniq -c|sort -r|awk '$1!=L{L=$1;c=++a}{print $2, c}'

结果:

tr 1
rand 1
ora 1
remo 2
hello 2

<强>解释

第一步:排序文件为uniq期望。

$ sort file
hello
hello
ora
ora
ora
rand
rand
rand
remo
remo
tr
tr
tr

来自uniq手册页:

  

输入中的重复如果不是,将无法检测到   相邻,因此可能需要先对文件进行排序。

下一步:让计算

$ sort file|uniq -c                                            
   2 hello
   3 ora
   3 rand
   2 remo
   3 tr
  

-c在每个输出行前面加上输入行的次数,后跟一个空格。

第三步,排序再次以反向顺序排序

$ sort file|uniq -c|sort -r                                    
   3 tr
   3 rand
   3 ora
   2 remo
   2 hello

最后 awk部分:

awk '$1!=L{L=$1;c=++a}{print$2, c}'

这个想法很简单:

$1!=L:仅在第一个字段(引用计数的字段)变换时增加等级c=++a 。 我们还将使用L来存储$1上一个/上一个值

{print $2, c}:[适用于所有记录]打印当前单词(第二个字段),然后是排名。

答案 1 :(得分:1)

Kludgy解决方案(datamashmktempnl),直到想到更清洁的东西:

x=`mktemp`
datamash  -g 1 -s count 1 < file | 
datamash -s -g 2 reverse | 
tac | tee $x | cut -f1 | uniq | nl | 
while read a b ; do 
    sed -n "/^$b/{s/^$b\W*\(.*\)/\1\t$a/p}" $x ; 
done ; rm $x

输出:

tr      1
rand    1
ora     1
remo    2
hello   2

答案 2 :(得分:1)

使用 GNU awk,结果相同,但订单略有不同

<强>一衬垫:

awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_desc"}{a[$1]++}END{for(i in a){ if(a[i]!=p){r++; p=a[i]}print i,r}}' infile

<强>解释

awk '
     BEGIN{
             PROCINFO["sorted_in"]="@val_num_desc"
          }
          {
             a[$1]++
          }
       END{
           for(i in a)
           { 
              if(a[i]!=p)
              {
                r++; 
                p=a[i]
              }
              print i,r
           }
          }
  ' infile

参考:

https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html

https://www.gnu.org/software/gawk/manual/html_node/Controlling-Array-Traversal.html

  • PROCINFO["sorted_in"] - 为了控制for循环期间gawk遍历数组的顺序。

  • "@val_num_desc" - 被视为数字的值按从高到低的顺序排列。

  • a[$1]++ a是数组,$1是数组索引,数组a包含出现次数,数组键。

  • if(a[i]!=p){r++; p=a[i]}因为数组值按降序排序,只要数组值发生变化,增量r++p=a[i]变量保存以前的值,用于比较。< / p>

<强>输入:

$ cat infile
ora
remo
ora
ora
hello
tr
tr
tr
remo
rand
rand
rand
hello

<强>输出:

$ awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_desc"}{a[$1]++}END{for(i in a){ if(a[i]!=p){r++; p=a[i]}print i,r}}' infile
rand 1
tr 1
ora 1
hello 2
remo 2