使用命令行工具按排序顺序计算重复项


82

我有一个命令(cmd1),它可以通过日志文件来过滤出一组数字。这些数字是随机顺序的,因此我使用sort -gr获取数字的反向排序列表。此排序列表中可能有重复项。我需要在该列表中找到每个唯一编号的计数。

例如,如果cmd1的输出是:

100 
100 
100 
99 
99 
26 
25 
24 
24

我需要另一个命令,可以将上述输出传递到该命令,以便得到:

100     3
99      2
26      1
25      1
24      2


Answers:


94

怎么样;

$ echo "100 100 100 99 99 26 25 24 24" \
    | tr " " "\n" \
    | sort \
    | uniq -c \
    | sort -k2nr \
    | awk '{printf("%s\t%s\n",$2,$1)}END{print}'

结果是:

100 3
99  2
26  1
25  1
24  2

1
我运行了它,结果产生了$ 1,$ 2的额外打印声明:100 3 99 2 26 1 25 1 24 2 2 24
Mittenchops 2013年

3
以下内容在结果之间添加了一条新线,并在末尾删除了多余的线: echo "100 100 100 99 99 26 25 24 24" | tr " " "\n" | sort | uniq -c | sort -k2nr | awk '{printf("%s\t%s\n",$2,$1)}END{print}' | head -n -1这样您将获得:100 3 99 2 26 1 25 1 24 2
伍迪

关于语法的注意事项,您可以使用管道结束一行而不是使用反斜杠。
wjandrea '19

53

uniq -c 至少适用于GNU uniq 8.23,并且完全符合您的要求(假设已排序的输入)。


2
如果输入未排序,则只需添加sort命令:sort file_name | uniq -c
Mikhail Geyer

太棒了 也可以在Mac OS X上使用!在Mojave 10.14.6上测试。
bappak

10

如果顺序不重要

# echo "100 100 100 99 99 26 25 24 24" | awk '{for(i=1;i<=NF;i++)a[$i]++}END{for(o in a) printf "%s %s ",o,a[o]}'
26 1 100 3 99 2 24 2 25 1

+1可减少3个管道。如果您能详细说明这是如何工作的,那将真是让我感到困惑。;-) 谢谢。
SaxDaddy

9

对数字进行反向数字排序,然后计算重复项,然后交换左右单词。对齐列。

printf '%d\n' 100 99 26 25 100 24 100 24 99 \
   | sort -nr | uniq -c | awk '{printf "%-8s%s\n", $2, $1}'
100     3
99      2
26      1
25      1
24      2

2

在Bash中,我们可以使用关联数组对每个输入值的实例进行计数。假设我们有命令$cmd1,例如

#!/bin/bash

cmd1='printf %d\n 100 99 26 25 100 24 100 24 99'

然后,我们可以a使用++数学运算符对相关数组条目计数数组变量中的值:

while read i
do
    ((++a["$i"]))
done < <($cmd1)

我们可以打印结果值:

for i in "${!a[@]}"
do
    echo "$i ${a[$i]}"
done

如果输出顺序很重要,则可能需要外部sort键:

for i in $(printf '%s\n' "${!a[@]}" | sort -nr)
do
    echo "$i ${a[$i]}"
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.