komut satırı araçlarını kullanarak yinelenenleri sıralanmış bir sırayla sayma


82

Bir sayı kümesini filtrelemek için bir günlük dosyasında greps yapan bir komutum (cmd1) var. Sayılar rastgele sıradadır, bu yüzden ters sıralı bir sayı listesi elde etmek için sort -gr kullanıyorum. Bu sıralanmış listede kopyalar olabilir. Bu listedeki her benzersiz sayının sayısını bulmam gerekiyor.

Örneğin, cmd1'in çıktısı:

100 
100 
100 
99 
99 
26 
25 
24 
24

Yukarıdaki çıktıyı yönlendirebileceğim başka bir komuta ihtiyacım var, böylece şunu elde ederim:

100     3
99      2
26      1
25      1
24      2


Yanıtlar:


94

ne dersin;

$ 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}'

Sonuç:

100 3
99  2
26  1
25  1
24  2

1
Bunu çalıştırdım ve sonunda 1 $, 2 $ 'lık ekstra bir baskı beyanı üretti:100 3 99 2 26 1 25 1 24 2 2 24
Mittenchops

3
Aşağıdakiler, sonuçlar arasına yeni bir satır ekler ve sondaki fazladan çizgiyi kaldırır: 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 -1böylece şunu elde edersiniz:100 3 99 2 26 1 25 1 24 2
Woody

Sözdizimi hakkında not, ters eğik çizgi kullanmak yerine bir çizgiyi boru ile sonlandırabilirsiniz.
wjandrea

54

uniq -c en azından GNU uniq 8.23 ​​için çalışır ve tam olarak istediğinizi yapar (sıralı girdi varsayılarak).


2
girişin sıralanmamış olması durumunda, sadece şu sortkomutu ekleyin :sort file_name | uniq -c
Mikhail Geyer

Harika. Mac OS X'te de çalışıyor! Mojave 10.14.6'da test edilmiştir.
bappak

10

sipariş önemli değilse

# 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

Bunu 3 daha az boru ile yapmak için +1. Bunun nasıl çalıştığını açıklarsanız harika olurdu, çünkü kafamı karıştırdı. ;-) Teşekkürler.
SaxDaddy

9

Sayıları tersten sayısal olarak sıralayın, ardından yinelenenleri sayın, ardından sol ve sağ sözcükleri değiştirin. Sütunlara hizalayın.

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'de, her girdi değerinin örneklerini saymak için ilişkilendirilebilir bir dizi kullanabiliriz . Komuta sahip olduğumuzu varsayarsak $cmd1, örneğin

#!/bin/bash

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

Ardından , ilgili dizi girdilerindeki matematiksel operatörü akullanarak dizi değişkenindeki değerleri sayabiliriz ++:

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

Elde edilen değerleri yazdırabiliriz:

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

Çıktı sırası önemliyse, sortanahtarların bir dışına ihtiyacımız olabilir :

for i in $(printf '%s\n' "${!a[@]}" | sort -nr)
do
    echo "$i ${a[$i]}"
done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.