打印重复计数而不删除终端中的重复项

Print duplicate count without removing duplicates in Terminal

我刚开始使用 mac 上的终端,并且有一个很大的 .tsv 文件,其中包含一个项目列表和旁边的两个值。我希望能够在不删除其他数据的情况下打印第一次出现该项目的重复次数。

我知道 cut -f 1 |排序 | uniq -c 但这会删除很多我想保留以供分析的有价值的数据。我正在阅读有关 awk 和 grep 的内容,但我想我需要一些帮助。

这是我正在尝试处理的文件示例:

fruit   number  reference
apple   12  342
apple   13  345
apple   43  4772
banana  19  234
banana  73  3242
peach   131 53423
peach   234 3266
peach   242 324
peach   131 56758
peaches 29  2434

理想情况下,输出看起来像这样:

fruit   number  reference   fruit_count
apple   12  342 3
apple   13  345 
apple   43  4772    
banana  19  234 2
banana  73  3242    
peach   131 53423   4
peach   234 3266    
peach   242 324 
peach   131 56758   
peaches 29  2434    1

这样的事情有可能吗?我可以使用公式获得所需的输出 excel,但文件太大并且一直崩溃。任何帮助将不胜感激。

编辑:添加我当前的解决方案(不符合我的要求)

cut -f 1 fruitsample.txt | sort | uniq -c | sed -e 's/ *//' -e 's/ / /'

这给了我预期的计数,将 uniq -c 的标准计数 + space 输出替换为制表符,但它也对 header 行进行排序并删除了第二列和第三列.

在Excel上,我可以用公式=IF(COUNTIF(A:A2,A2)=1,COUNTIF(A:A,A2),"")往下填。我正在处理的文件有将近 68 万行数据,Excel 试图计算那么多行时遇到了困难。

正如我所提到的,我是一个正在寻找指导的初学者。我只是不太熟悉 awk 或 grep。再次感谢!

awk 救援!

awk 'NR==FNR {a[]++; next} 
     FNR==1  {print [=10=], "fruit_count"; next} 
      in a {$(NF+1)=a[]; delete a[]}1' file{,} | 
column -t

fruit    number  reference  fruit_count
apple    12      342        3
apple    13      345
apple    43      4772
banana   19      234        2
banana   73      3242
peach    131     53423      4
peach    234     3266
peach    242     324
peach    131     56758
peaches  29      2434       1

为了解释主要思想,我将使用没有 header 和未排序数据的更简单的结构

$ cat file
apple
banana
apple
apple
cherry
banana

$ awk 'NR==FNR {a[]++; next}            # in the first pass, save key counts
                 in a                   # if the key in map
                        {$(NF+1)=a[];   # add the count as a last column
                         delete a[]}    # remove key from map
                1                         # print
       ' file{,} |                        # bash shorthand for: file file
  column -t                               # pretty print columns 


apple   3
banana  2
apple
apple
cherry  1
banana

对于简化示例,使用 unix 工具链您可以实现相同的效果

join -a1 -11 -22 -o1.2,2.1 <(cat -n file) <(cat -n file | sort -k2 | uniq -c -f1)

添加 header 需要更多的技巧;这是 awk 的亮点。

另一个使用awk和double-tacs:

$ tac file | awk '
NR>1 {print q, (p==?"":++c)}                  # p previous first field, q previous record
     {c=(p==?c+1:0); p=; q=[=10=]}              # c is the counter
END  {print q, "fruit_count"}
' | tac
fruit   number  reference fruit_count
apple   12  342 3
apple   13  345
apple   43  4772
banana  19  234 2
banana  73  3242
peach   131 53423 4
peach   234 3266
peach   242 324
peach   131 56758
peaches 29  2434 1

这会在一次输入文件中完成您想要的操作,并且一次仅将 1 个水果的值存储在内存中,因此尽管您的文件对于 MS 来说太大了,但它不应该出现性能或内存问题- Excel:

$ cat tst.awk
NR==1 { print [=10=], "fruit_count"; next }
 != prev { prt() }
{ arr[++cnt] = [=10=]; prev =  }
END { prt() }
function prt(    i) {
    if (cnt) {
        print arr[1], cnt
        for (i=2; i <= cnt; i++) {
            print arr[i]
        }
        delete arr
        cnt = 0
    }
}

$ awk -f tst.awk file | column -t
fruit    number  reference  fruit_count
apple    12      342        3
apple    13      345
apple    43      4772
banana   19      234        2
banana   73      3242
peach    131     53423      4
peach    234     3266
peach    242     324
peach    131     56758
peaches  29      2434       1