बैश स्क्रिप्ट: फ़ाइल में अद्वितीय पंक्तियों की गणना करें


129

परिस्थिति:

मेरे पास एक बड़ी फ़ाइल (लाखों पंक्तियाँ) हैं जिनमें कई घंटे नेटवर्क कैप्चर, एक आईपी / पोर्ट प्रति लाइन से आईपी पते और पोर्ट होते हैं। लाइनें इस प्रारूप की हैं:

ip.ad.dre.ss[:port]

वांछित परिणाम:

लॉगिंग करते समय मुझे प्राप्त प्रत्येक पैकेट के लिए एक प्रविष्टि है, इसलिए बहुत सारे डुप्लिकेट पते हैं। मैं इसे किसी प्रकार की शेल स्क्रिप्ट के माध्यम से चलाने में सक्षम होना चाहूंगा जो इसे प्रारूप की रेखाओं तक कम करने में सक्षम होगा

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

countउस विशिष्ट पते (और पोर्ट) की घटनाओं की संख्या कहां है। कोई विशेष काम नहीं करना है, विभिन्न बंदरगाहों को अलग-अलग पते के रूप में मानें।

अब तक, मैं इस कमांड का उपयोग लॉग फाइल से सभी आईपी एड्रेस को स्क्रैप करने के लिए कर रहा हूँ:

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

उस से, मैं अपने पते द्वारा भेजे गए सभी आईपी पते को निकालने के लिए एक बहुत ही सरल रीजेक्स का उपयोग कर सकता हूं (जो मुझे परवाह नहीं है)

फिर मैं अद्वितीय प्रविष्टियों को निकालने के लिए निम्नलिखित का उपयोग कर सकता हूं:

sort -u ips.txt > intermediate.txt

मुझे नहीं पता कि मैं किस तरह से किसी तरह से रेखा की गणना कर सकता हूं।

जवाबों:


303

आप uniqक्रमबद्ध बार-बार लाइनों की गिनती प्राप्त करने के लिए कमांड का उपयोग कर सकते हैं :

sort ips.txt | uniq -c

शीर्ष पर सबसे लगातार परिणाम प्राप्त करने के लिए (पीटर जरिक के लिए धन्यवाद):

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

10
मुझे यह पसंद है कि -bgrसंयोगवश किस तरह से एक महामारी की तरह दिखता है bigger, जो कि हम शीर्ष पर चाहते हैं।
dwanderson

1
अपने .bashrcया .bash_aliasesफ़ाइल के लिए एक छोटे समारोह के रूप में function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }:। द्वारा कॉल करें countuniquelines myfile.txt
जोहान

यकीन नहीं होता क्यों नहीं sort -nr
नकीलोन

5

अद्वितीय पंक्तियों की कुल संख्या (यानी डुप्लिकेट लाइनों पर विचार नहीं करना) को गिनने के लिए हम इसका उपयोग कर सकते हैं uniqया इसके साथ जाग सकते हैं wc:

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

अक्क की सरणियाँ साहचर्य हैं इसलिए यह छँटाई की तुलना में थोड़ी तेज़ हो सकती हैं।

टेक्स्ट फ़ाइल बनाना:

$  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

दिलचस्प। विशाल डेटासेट के लिए एक प्रशंसनीय अंतर हो सकता है
Wug

1

यह दोहराया लाइनों की गिनती प्राप्त करने का सबसे तेज़ तरीका है और उन्हें कम से कम लगातार सबसे अधिक बार बोया गया है:

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

यदि आपको प्रदर्शन की परवाह नहीं है और आप कुछ आसान याद रखना चाहते हैं, तो बस दौड़ें:

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

पुनश्च:

सॉर्ट करें- फ़ील्ड को एक संख्या के रूप में पार्स करें, यह सही है क्योंकि हम गणनाओं का उपयोग कर रहे हैं।


!में {!seen[$0]++}यहाँ अनावश्यक है, क्योंकि हम केवल पर मुद्रण करना END
आमिर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.