2011-05-04 8 views
6

मैं फ़ाइलहेडल से डुप्लिकेट लाइनों को मुद्रित करने की कोशिश कर रहा हूं, उन्हें हटा नहीं सकता हूं या अन्य प्रश्नों पर मैंने जो कुछ भी देखा है उसे हटा नहीं रहा हूं। मेरे पास पेर्ल के साथ पर्याप्त अनुभव नहीं है ताकि इसे जल्दी से करने में सक्षम हो, इसलिए मैं यहां पूछ रहा हूं। ऐसा करने का तरीका क्या है?पर्ल - फ़ाइल या सरणी में डुप्लिकेट लाइनें पाएं

my %seen; 
while (<>) { 
    print if $seen{$_}++; 
} 

"एक लाइनर" के रूप में::

perl -ne 'print if $seen{$_}++' 

अधिक डेटा

+2

एक बहुत इनपुट के आकार पर निर्भर करता है, लाइनों के आकार और डुप्लिकेट की संभावित संख्या। यदि स्मृति आवश्यकताएं कम हैं, तो '% डुप्लीकेट्स हैश वाले समाधान पर्याप्त हैं। –

+0

वे हैं। मैं बस कुछ जांचने के लिए फ़ाइलहेडल का उपयोग कर रहा हूं। ऐसा लगता है कि कोई डुप्लिकेट नहीं है, तो यह अच्छा है। – Chris

उत्तर

22

मानक पर्ल shorthands ले रहे हैं? यह <file name>:<line number>:<line> प्रिंट:

perl -ne 'print ($ARGV eq "-" ? "" : "$ARGV:"), "$.:$_" if $seen{$_}++' 

%seen का स्पष्टीकरण:

  • %seen एक हैश की घोषणा की। इनपुट में प्रत्येक अद्वितीय लाइन (जो while(<>) से इस मामले में आ रही है) $seen{$_} में लाइन के पाठ द्वारा नामित हैश में स्केलर स्लॉट होगा (यह $_{} ब्रेसिज़ में कर रहा है)।
  • पोस्टफ़िक्स वेतन वृद्धि ऑपरेटर (x++) का उपयोग करना हम ले हमारे अभिव्यक्ति के लिए मूल्य, अभिव्यक्ति के बाद यह वेतन वृद्धि को याद। इसलिए, यदि हमने $seen{$_} को "देखा" नहीं देखा है, लेकिन जब इसे एक संख्यात्मक "संदर्भ" में मजबूर किया जाता है, तो इसे 0 - और झूठी के रूप में लिया जाता है।
  • तो यह 1.

तो, करने के लिए वृद्धि की जाती है, जब while चलाने के लिए शुरू होता है, सभी लाइनें हैं "शून्य" (अगर यह आपकी मदद करता है के रूप में "नहीं %seen" लाइनों के बारे में सोच सकते हैं) तो सबसे पहले समय हम एक लाइन देखते हैं, perl अपरिभाषित मान लेता है - जो if में विफल रहता है - और स्केलर स्लॉट पर गिनती को 1 तक बढ़ा देता है। इस प्रकार, यह किसी भी भविष्य की घटनाओं के लिए 1 है जिस बिंदु पर यह if स्थिति को पास करता है और इसे मुद्रित किया जाता है।

जैसा कि मैंने ऊपर कहा है, %seen एक हैश घोषित करता है, लेकिन strict बंद हो गया है, किसी भी परिवर्तनीय अभिव्यक्ति को स्थान पर बनाया जा सकता है। तो पहली बार perl $seen{$_} देखता है यह जानता है कि मैं %seen की तलाश में हूं, इसमें यह नहीं है, इसलिए यह इसे बनाता है।

इसके बारे में एक अच्छी बात यह है कि अंत में, यदि आप इसका उपयोग करने की देखभाल करते हैं, तो आप की गणना है कि प्रत्येक पंक्ति को कितनी बार दोहराया गया था।

+0

+1 अच्छा एक-लाइनर – mcgrailm

+0

क्या आप समझा सकते हैं कि $ {$ _} ++ वास्तव में कैसे काम करता है? मुझे लगता है कि यह वर्तमान लाइन के मान को हैश तालिका में असाइन कर रहा है, लेकिन ++ क्या कर रहा है जो इसे डुप्लिकेट ढूंढता है? – Chris

+1

$ देखा {$ _} हैश% में एक मान को संदर्भित करता है, कुंजी $ _ के साथ, जो वर्तमान रेखा है। ++ ऑपरेटर हैश मान बढ़ाएगा। इसका मतलब है, पहली बार एक कुंजी दिखाई देती है, इसका मूल्य गलत होगा, और प्रिंट नहीं होगा। बाद के समय यह देखा जाता है, यह> 0 होगा, और इसलिए प्रिंट निष्पादित होगा, और डिफ़ॉल्ट रूप से तर्क के बिना प्रिंट $ _ चर प्रिंट करता है। – TLP

3

कोशिश इस

#!/usr/bin/perl -w 
use strict; 
use warnings; 

my %duplicates; 
while (<DATA>) { 
    print if !defined $duplicates{$_}; 
    $duplicates{$_}++; 
} 
+0

मैं तब तक प्रिंट करूंगा जब तक कि $ डुप्लिकेट {$ _} 'मौजूद न हो। और '-w' के लिए +1,' सख्त उपयोग करें 'और' चेतावनियों का उपयोग करें '। – Blrfl

0

आप एक यूनिक्स की तरह सिस्टम है, तो आप uniq उपयोग कर सकते हैं:

uniq -d foo 

या

uniq -D foo 

आप क्या चाहते हैं क्या करना चाहिए। अधिक जानकारी: man uniq

2

प्रिंटों केवल एक बार ड्यूप्स:

perl -ne "print if $seen{$_}++ == 1" 
+1

यह 'sort file.txt | जैसा है एक विशिष्ट यूनिक्स शैल में uniq -d' (केवल डुप्लीकेट प्रिंट करें)। क्या 'sort file.txt | का एक सरल समतुल्य है uniq -u' (केवल अद्वितीय लाइनों मुद्रित)? –

संबंधित मुद्दे