đếm các bản sao trong một trình tự được sắp xếp bằng các công cụ dòng lệnh


82

Tôi có một lệnh (cmd1) chuyển qua tệp nhật ký để lọc ra một tập hợp số. Các số theo thứ tự ngẫu nhiên, vì vậy tôi sử dụng sắp xếp -gr để có được danh sách các số được sắp xếp ngược lại. Có thể có các bản sao trong danh sách được sắp xếp này. Tôi cần tìm số lượng cho mỗi số duy nhất trong danh sách đó.

Ví dụ: nếu đầu ra của cmd1 là:

100 
100 
100 
99 
99 
26 
25 
24 
24

Tôi cần một lệnh khác mà tôi có thể chuyển đầu ra ở trên đến, do đó, tôi nhận được:

100     3
99      2
26      1
25      1
24      2


Câu trả lời:


94

làm thế nào về;

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

Kết quả là :

100 3
99  2
26  1
25  1
24  2

1
Tôi đã chạy điều này và nó tạo ra một báo cáo in thêm là $ 1, $ 2 ở cuối:100 3 99 2 26 1 25 1 24 2 2 24
Mittenchops

3
Phần sau thêm một dòng mới giữa các kết quả và xóa dòng thừa ở cuối: 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 -1vì vậy bạn nhận được:100 3 99 2 26 1 25 1 24 2
Woody

Lưu ý về cú pháp, bạn có thể kết thúc một dòng bằng dấu gạch ngang thay vì sử dụng dấu gạch chéo ngược.
wjandrea 14/07/19

53

uniq -c ít nhất hoạt động cho GNU uniq 8.23 ​​và làm chính xác những gì bạn muốn (giả sử đầu vào được sắp xếp).


2
trong trường hợp nếu đầu vào không được sắp xếp, sau đó chỉ cần thêm sortlệnh:sort file_name | uniq -c
Mikhail Geyer

Tuyệt vời. Hoạt động trên Mac OS X! Đã thử nghiệm trên Mojave 10.14.6.
bappak

10

nếu thứ tự không quan trọng

# 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 để làm điều này với 3 ống nhỏ hơn. Sẽ thật tuyệt nếu bạn có thể giải thích rõ hơn về cách thức hoạt động của điều này. B / c nó làm tôi bối rối. ;-) Cảm ơn.
SaxDaddy

9

Sắp xếp ngược lại các số theo thứ tự, sau đó đếm các từ trùng lặp, sau đó hoán đổi các từ bên trái và bên phải. Căn chỉnh thành các cột.

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

Trong Bash, chúng ta có thể sử dụng một mảng kết hợp để đếm các phiên bản của mỗi giá trị đầu vào. Giả sử chúng ta có lệnh $cmd1, ví dụ:

#!/bin/bash

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

Sau đó, chúng ta có thể đếm các giá trị trong biến mảng abằng cách sử dụng ++toán tử toán học trên các mục nhập mảng có liên quan:

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

Chúng tôi có thể in các giá trị kết quả:

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

Nếu thứ tự đầu ra là quan trọng, chúng tôi có thể cần một bên ngoài sortcủa các khóa:

for i in $(printf '%s\n' "${!a[@]}" | sort -nr)
do
    echo "$i ${a[$i]}"
done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.