Bash Script: đếm các dòng duy nhất trong tệp


129

Tình hình:

Tôi có một tệp lớn (hàng triệu dòng) chứa địa chỉ IP và cổng từ một lần chụp mạng vài giờ, một ip / cổng trên mỗi dòng. Các dòng có định dạng này:

ip.ad.dre.ss[:port]

Kết quả như ý:

Có một mục nhập cho mỗi gói tôi nhận được khi đăng nhập, vì vậy có rất nhiều địa chỉ trùng lặp. Tôi muốn có thể chạy nó thông qua một tập lệnh shell nào đó để có thể giảm nó thành các dòng có định dạng

ip.ad.dre.ss[:port] count

nơi countlà số lần xuất hiện của địa chỉ cụ thể (và cảng). Không có công việc đặc biệt phải được thực hiện, coi các cổng khác nhau như các địa chỉ khác nhau.

Cho đến nay, tôi đang sử dụng lệnh này để cạo tất cả các địa chỉ IP từ tệp nhật ký:

grep -o -E [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(:[0-9]+)? ip_traffic-1.log > ips.txt

Từ đó, tôi có thể sử dụng một regex khá đơn giản để loại bỏ tất cả các địa chỉ IP được gửi bởi địa chỉ của tôi (mà tôi không quan tâm)

Sau đó tôi có thể sử dụng các mục sau để trích xuất các mục duy nhất:

sort -u ips.txt > intermediate.txt

Tôi không biết làm thế nào tôi có thể tổng hợp các dòng đếm bằng cách nào đó với sắp xếp.

Câu trả lời:


303

Bạn có thể sử dụng uniqlệnh để lấy số lượng các dòng lặp lại được sắp xếp:

sort ips.txt | uniq -c

Để có được kết quả thường xuyên nhất ở đầu (nhờ Peter Jaric):

sort ips.txt | uniq -c | sort -bgr

10
Tôi thích làm thế nào -bgrtrùng hợp trông giống như một người ghi nhớ cho bigger, đó là những gì chúng ta muốn ở đầu.
lùn

1
Là một chức năng nhỏ cho .bashrchoặc .bash_aliasestập tin của bạn : function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }. Gọi bằng countuniquelines myfile.txt.
Johan

Không chắc tại sao không sort -nr.
Nakilon

5

Để đếm tổng số dòng duy nhất (nghĩa là không xem xét các dòng trùng lặp), chúng ta có thể sử dụng uniqhoặc Awk với wc:

sort ips.txt | uniq | wc -l
awk '!seen[$0]++' ips.txt | wc -l

Các mảng của Awk là kết hợp để nó có thể chạy nhanh hơn một chút so với sắp xếp.

Tạo tập tin văn bản:

$  for i in {1..100000}; do echo $RANDOM; done > random.txt
$ time sort random.txt | uniq | wc -l
31175

real    0m1.193s
user    0m0.701s
sys     0m0.388s

$ time awk '!seen[$0]++' random.txt | wc -l
31175

real    0m0.675s
user    0m0.108s
sys     0m0.171s

Hấp dẫn. Có thể tạo ra sự khác biệt đáng kể cho các bộ dữ liệu khổng lồ
Wug

1

Đây là cách nhanh nhất để đếm số lượng các dòng lặp đi lặp lại và chúng được in độc đáo theo tỷ lệ ít thường xuyên nhất đến thường xuyên nhất:

awk '{!seen[$0]++}END{for (i in seen) print seen[i], i}' ips.txt | sort -n

Nếu bạn không quan tâm đến hiệu suất và bạn muốn một cái gì đó dễ nhớ hơn, thì chỉ cần chạy:

sort ips.txt | uniq -c | sort -n

Tái bút

sắp xếp -n phân tích trường dưới dạng một số, điều đó đúng vì chúng ta sắp xếp bằng cách sử dụng số đếm.


Các !tại {!seen[$0]++}là không cần thiết ở đây, như chúng ta chỉ làm việc in ấn tại END.
Amir
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.