获取bash中列中唯一值的计数

我有几列的制表符分隔的文件。 我想计算一个文件夹中所有文件的列中不同值的出现频率,并按照计数递减顺序(最高计数优先)进行sorting。 我将如何在Linux命令行环境中完成此操作?

它可以使用任何常见的命令行语言,如awk,perl,python等

要查看第二列的频率计数(例如):

awk -F '\t' '{print $2}' * | sort | uniq -c | sort -nr 

fileA.txt

 zza abc wde 

fileB.txt

 tre zda agc 

fileC.txt

 zra vdc amc 

结果:

  3 d 2 r 1 z 1 m 1 g 1 b 

这是一个在shell中执行的方法:

 FIELD=2 cut -f $FIELD * | sort| uniq -c |sort -nr 

这就是bash所擅长的。

GNU网站提供了这个不错的awk脚本,它可以打印单词及其频率。

可能的变化:

  • 您可以通过sort -nr (并反转wordfreq[word] )来查看结果,以降序排列。
  • 如果你想要一个特定的列,你可以省略for循环,并简单地写freq[3]++ – 用列号replace3。

开始:

  # wordfreq.awk --- print list of word frequencies { $0 = tolower($0) # remove case distinctions # remove punctuation gsub(/[^[:alnum:]_[:blank:]]/, "", $0) for (i = 1; i <= NF; i++) freq[$i]++ } END { for (word in freq) printf "%s\t%d\n", word, freq[word] } 

Perl的

此代码计算所有列的出现次数,并为其中的每一列打印sorting报告:

 # columnvalues.pl while (<>) { @Fields = split /\s+/; for $i ( 0 .. $#Fields ) { $result[$i]{$Fields[$i]}++ }; } for $j ( 0 .. $#result ) { print "column $j:\n"; @values = keys %{$result[$j]}; @sorted = sort { $result[$j]{$b} <=> $result[$j]{$a} || $a cmp $b } @values; for $k ( @sorted ) { print " $k $result[$j]{$k}\n" } } 

将文本保存为columnvalues.pl
运行它为: perl columnvalues.pl files*

说明

在顶层while循环中:
*循环组合input文件的每一行
*将行分割成@Fields数组
*对于每一列,递增结果数组散列数据结构

在顶级for循环中:
*循环结果数组
*打印列号
*获取该列中使用的值
*按出现次数sorting值
*根据数值进行二次sorting(例如b vs g vs m vs z)
*使用sorting列表遍历结果散列
*打印每个事件的值和数量

结果基于@Dennis提供的示例input文件

 column 0: a 3 z 3 t 1 v 1 w 1 column 1: d 3 r 2 b 1 g 1 m 1 z 1 column 2: c 4 a 3 e 2 

.csvinput

如果您的input文件是.csv,请将/\s+/更改为/,/

困惑

在一个丑陋的比赛中,Perl的装备特别好。
这一行也是一样的:

 perl -lane 'for $i (0..$#F){$g[$i]{$F[$i]}++};END{for $j (0..$#g){print "$j:";for $k (sort{$g[$j]{$b}<=>$g[$j]{$a}||$a cmp $b} keys %{$g[$j]}){print " $k $g[$j]{$k}"}}}' files* 

ruby(1.9+)

 #!/usr/bin/env ruby Dir["*"].each do |file| h=Hash.new(0) open(file).each do |row| row.chomp.split("\t").each do |w| h[ w ] += 1 end end h.sort{|a,b| b[1]<=>a[1] }.each{|x,y| print "#{x}:#{y}\n" } end