किसी फ़ाइल में डुप्लिकेट लाइनें ढूंढें और गिनें कि प्रत्येक पंक्ति को कितनी बार दोहराया गया था?


529

मान लीजिए कि मेरे पास निम्नलिखित के समान एक फाइल है:

123 
123 
234 
234 
123 
345

मुझे लगता है कि कितनी बार '123' को दोहराया गया था, कितनी बार '234' को दोहराया गया था, आदि। तो आदर्श रूप में, आउटपुट जैसा होगा:

123  3 
234  2 
345  1

4
आप किस भाषा का उपयोग करना चाहते हैं?
VMAtm

जवाबों:


791

मान लें कि प्रति पंक्ति एक संख्या है:

sort <file> | uniq -c

आप --countलिनक्स पर जीएनयू संस्करण के साथ अधिक वर्बोज़ फ़्लैग का भी उपयोग कर सकते हैं :

sort <file> | uniq --count

3
यह वह है जो मैं हालांकि एल्गोरिथ्म में करता हूं यह सबसे कुशल दृष्टिकोण (O (n लॉग एन) * avg_line_len है जहां n लाइनों की संख्या है) लगता है। मैं उन फाइलों पर काम कर रहा हूं जो कई गीगाबाइट बड़ी हैं, इसलिए प्रदर्शन एक प्रमुख मुद्दा है। मुझे आश्चर्य है कि क्या कोई ऐसा उपकरण है जो एक उपसर्ग वृक्ष का उपयोग करके केवल एक पास में गिनती करता है (मेरे मामले में तार में अक्सर आम उपसर्ग होते हैं) या इसी तरह, कि हे (n) * avg_line_len में चाल करना चाहिए। क्या कोई ऐसे कमांडलाइन टूल को जानता है?
Droggl

21
एक अतिरिक्त कदम एक अंतिम 'सॉर्ट एन' कमांड में उस के आउटपुट को पाइप करना है। यह उन परिणामों को क्रमबद्ध करेगा जिनके द्वारा लाइनें सबसे अधिक बार होती हैं।
samoz

79
यदि आप केवल डुप्लिकेट लाइनें प्रिंट करना चाहते हैं, तो 'uniq -d' का उपयोग करें
दिमित्रीसंडालोव

6
यदि आप परिणाम को फिर से क्रमबद्ध करना चाहते हैं, तो आप sortफिर से उपयोग कर सकते हैं जैसे:sort <file> | uniq -c | sort -n
अभिषेक कश्यप

413

यह डुप्लिकेट लाइनों को केवल काउंट के साथ प्रिंट करेगा :

sort FILE | uniq -cd

या, GNU लंबे विकल्पों के साथ (लिनक्स पर):

sort FILE | uniq --count --repeated

पर बीएसडी और OSX आप ग्रेप उपयोग करने के लिए अद्वितीय लाइनों बाहर फिल्टर करने के लिए:

sort FILE | uniq -c | grep -v '^ *1 '

दिए गए उदाहरण के लिए, परिणाम होगा:

  3 123
  2 234

यदि आप सभी लाइनों के लिए गिनती प्रिंट करना चाहते हैं, जिनमें केवल एक बार दिखाई देते हैं:

sort FILE | uniq -c

या, GNU लंबे विकल्पों के साथ (लिनक्स पर):

sort FILE | uniq --count

दिए गए इनपुट के लिए, आउटपुट है:

  3 123
  2 234
  1 345

शीर्ष पर सबसे लगातार लाइनों के साथ आउटपुट को सॉर्ट करने के लिए , आप निम्न (सभी परिणाम प्राप्त करने के लिए) कर सकते हैं:

sort FILE | uniq -c | sort -nr

या, केवल डुप्लिकेट लाइनें प्राप्त करने के लिए, सबसे पहले अक्सर:

sort FILE | uniq -cd | sort -nr

OSX और BSD पर अंतिम एक बन जाता है:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr

1
--Repeated या -d विकल्प के साथ अच्छा बिंदु। "Grep 2" या इसी तरह के उपयोग से बहुत अधिक सटीक है!
लॉरी

मैं उन सभी पंक्तियों को पुनः प्राप्त करने के लिए इस आदेश को कैसे संशोधित कर सकता हूं जिनकी पुनरावृत्ति संख्या 100 से अधिक है?
ब्लैक_राइडर

@Black_Rider जोड़ने | sort -nया | sort -nrपाइप में पुनरावृत्ति गणना (क्रमशः आरोही या अवरोही) द्वारा आउटपुट को सॉर्ट किया जाएगा। यह वह नहीं है जो आप पूछ रहे हैं, लेकिन मैंने सोचा कि यह मदद कर सकता है।
एंड्रिया

1
@Black_Rider awk सभी प्रकार की गणनाएं करने में सक्षम है: आपके मामले में आप कर सकते हैं| awk '$1>100'
एंड्रिया

4
@fionbio ऐसा लगता है कि आप OSX uniq पर -c और -d का एक साथ उपयोग नहीं कर सकते । इशारा करने के लिए धन्यवाद। आप अद्वितीय रेखाओं को फ़िल्टर करने के लिए grep का उपयोग कर सकते हैं :sort FILE | uniq -c | grep -v '^ *1 '
Andrea

72

एकाधिक फ़ाइलों में डुप्लिकेट लाइनों को खोजने और गिनने के लिए, आप निम्न कमांड आज़मा सकते हैं:

sort <files> | uniq -c | sort -nr

या:

cat <files> | sort | uniq -c | sort -nr

30

के जरिए :

awk '{dups[$1]++} END{for (num in dups) {print num,dups[num]}}' data

में awk 'dups[$1]++'आदेश, चर $1स्तम्भ 1 की सारी सामग्री को रखती है और वर्ग कोष्ठक सरणी का उपयोग कर सकते हैं। तो, dataफ़ाइल में लाइन के प्रत्येक 1 कॉलम के लिए , नाम के ऐरे का नोड dupsबढ़ा हुआ है।

और अंत में, हम चर के रूप में dupsसरणी के साथ लूपिंग कर रहे हैं numऔर पहले सहेजे गए नंबरों को प्रिंट करते हैं, फिर उनके द्वारा डुप्लिकेट किए गए मान की संख्या dups[num]

ध्यान दें कि आपकी इनपुट फ़ाइल में कुछ लाइनों के अंत में रिक्त स्थान हैं, यदि आप उन को साफ करते हैं, तो आप ऊपर दिए गए कमांड के $0स्थान पर उपयोग कर सकते हैं $1:)


1
क्या यह विचार करने से कुछ नहीं है कि हमारे पास uniqक्या है ?
नाथन फेलमैन

9
sort | uniqऔर awk सॉल्यूशन में काफी अलग परफॉर्मेंस और रिसोर्स ट्रेड-ऑफ्स होते हैं: अगर फाइल्स बड़ी हैं और अलग-अलग लाइनों की संख्या छोटी है, तो awk सॉल्यूशन बहुत अधिक कुशल है। यह लाइनों की संख्या में रैखिक है और अंतरिक्ष उपयोग विभिन्न लाइनों की संख्या में रैखिक है। OTOH, awk solution को सभी अलग-अलग लाइनों को मेमोरी में रखने की आवश्यकता होती है, जबकि (GNU) सॉर्ट अस्थायी फ़ाइलों का सहारा ले सकता है।
लार्स नोशिन्स्की

14

"Windows PowerShell" का उपयोग करते हुए विंडोज़ में मैंने इसे प्राप्त करने के लिए नीचे बताई गई कमांड का उपयोग किया

Get-Content .\file.txt | Group-Object | Select Name, Count

परिणाम को फ़िल्टर करने के लिए हम ऑब्जेक्ट-ऑब्जेक्ट Cmdlet का भी उपयोग कर सकते हैं

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count

क्या आप पिछले एक को छोड़कर डुप्लिकेट की सभी घटनाओं को हटा सकते हैं ... फ़ाइल के क्रम को बदले बिना?
जगराम

6

मान लें कि आपको एक मानक यूनिक्स शेल और / या साइबरविन पर्यावरण तक पहुंच मिली है:

tr -s ' ' '\n' < yourfile | sort | uniq -d -c
       ^--space char

मूल रूप से: सभी अंतरिक्ष वर्णों को लाइनब्रेक में परिवर्तित करें, फिर ट्रांस्लेट किए गए आउटपुट को सॉर्ट करें और इसे अनइक और डुप्लिकेट लाइनों को गिनने के लिए फ़ीड करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.