Awk - 计算行之间相似的单词

时间:2013-06-11 10:30:16

标签: bash awk

我有文字处理问题,我无法自行解决,因此我需要更聪明人的帮助 我的虚拟文件示例如下所示:

Winter    Sally    Additional_text
Winter    Sally    Additional_text
Winter    Nicole    Additional_text  
Spring    Lucy    Additional_text
Spring    Lucy    Additional_text
Spring    Caroline    Additional_text
Spring    Caroline    Additional_text
Summer    Emma    Additional_text
Autumn    Rita    Additional_text
Autumn    Rita    Additional_text
Autumn    Cristina     Additional_text
Autumn    Lucy's_sister     Additional_text
Autumn    Lucy's_sister     Additional_text

我想:
对于每个第一列项目,计算第二列中有多少个不同的名称。但我必须只计算那些名称:1)至少发生两次和2)至少有两个不同的名称(它们都至少出现两次)。
对于像这样的输出:

Time    Counts 
Spring    2
Autumn    2

输出说明:
Winter中有两个不同的名称,但Nicole只出现一次 - winter未报告;
Spring中,至少有两个不同的名称,每个名称至少出现两次 - 报告Spring中有多少个不同的名称;
Summer中,只有一个名称 - Summer未报告;
Autumn有三个不同的名称,但其中只有两个至少出现过两次 - 仅为RitaLucy's_sister报告了计数。

修改
我在awk和bash中的解决方案:

cut -d " " -f 1 FILE | sort -u > names
for i in $(cat names)
do 
   grep ^$i FILE | 
   awk '{print $2}' | 
   sort | 
   uniq -c | 
   awk -v VAR="$i" '($1>=2) {print VAR}' | 
   sort | 
   uniq -c | 
   awk '($1>=2) {print $2"\t"$1}' 
done

这太笨拙和重复,所以我想知道更简单的方法。

3 个答案:

答案 0 :(得分:2)

这是适用于您的awk命令:

awk '{sums[$1"~"$2]++} END {for (a in sums) {split(a, b, "~"); if (sums[a]>1) suma[b[1]]++;}
      for (k in suma) if (suma[k]>1) print k, suma[k]}' inFile

答案 1 :(得分:1)

awk '{kc[$1 "-" $2]++ } 
     END { for (k in kc) { if (kc[k]>=2) {f[gensub("-.*","","g",k)]++}}
           for (kk in f) { if (f[kk]>=2 ) {print kk, f[kk]}}}' INPUTFILE

适合你。首先,它计算数组中“FIRSTCOL-SECONDCOL”出现次数。然后在每次出现的文件末尾检查出现的次数,如果它大于1,则将FIRSTCOL存储在另一个数组中(作为键)并将值加1。然后打印每个FIRSTVAL及其值(如果它大于1)。我要把标题留给你。

注意 :如果第一列中有“-”,则会失败。

答案 2 :(得分:1)

这是使用GNU awk的一种方式。像:

一样运行
awk -f ./script.awk file

script.awk的内容:

BEGIN {
    OFS="\t"
}
{
    a[$1][ b[$1,$2]++ ]++
}
END {
    print "Time", "Counts";
    for (i in a) {
        for (j in a[i]) {
            if (j >= 1 && a[i][j] >= 2) {
                print i, a[i][j]
            }
        }
    }
}

或者,这是单行:

awk '{ a[$1][ b[$1,$2]++ ]++ } END { print "Time", "Counts"; for (i in a) for (j in a[i]) if (j >= 1 && a[i][j] >= 2) print i, a[i][j] }' OFS="\t" file

结果:

Time    Counts
Autumn  2
Spring  2