打印重复计数而不删除终端中的重复项
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-tac
s:
$ 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
我刚开始使用 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-tac
s:
$ 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