获取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(并反转word和freq[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