подсчет дубликатов в отсортированной последовательности с помощью инструментов командной строки

82

У меня есть команда (cmd1), которая просматривает файл журнала, чтобы отфильтровать набор чисел. Числа расположены в случайном порядке, поэтому я использую sort -gr, чтобы получить список чисел, отсортированный в обратном порядке. В этом отсортированном списке могут быть дубликаты. Мне нужно найти счетчик для каждого уникального числа в этом списке.

Например, если вывод cmd1:

100 
100 
100 
99 
99 
26 
25 
24 
24

Мне нужна другая команда, в которую я могу передать вывод, указанный выше, чтобы я получил:

100     3
99      2
26      1
25      1
24      2
Letronje
источник
связанные: serverfault.com/questions/37020/…
Дэвид Кэри,
связанные: stackoverflow.com/a/16980265/32453
rogerdpack

Ответы:

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
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
54

uniq -c работает как минимум для GNU uniq 8.23 ​​и делает именно то, что вы хотите (при условии отсортированного ввода).

Ибрагим
источник
2
в случае, если ввод не отсортирован, просто добавьте sortкоманду:sort file_name | uniq -c
Михаил Гейер
Потрясающе. Также работает на Mac OS X! Проверено на Mojave 10.14.6.
bappak 05
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
призрачная собака74
источник
+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
Тоби Спейт
источник