与此问题类似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
答案 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解决方案(datamash
,mktemp
,nl
,等),直到想到更清洁的东西:
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