एक फ़ाइल में आईडी खोजें जो दूसरे में नहीं हैं


9

मेरे पास दो फाइलें हैं:

abc.txt

abcd
xyz
pqrs

mno.txt

zzon
mkno
abcd
  • मैं जाँच करना चाहता हूँ कि "abcd" फाइल mno.txt में है या नहीं
  • यह आवश्यक नहीं है कि यदि "abcd" पहले abc.txt में है , तो यह mno.txt में भी पहली बार होगा ।
  • दोनों फाइलों में इस तरह की हजारों आईडी है।
  • मैं यह भी जांचना चाहता हूं कि कितने आईडी mno.txt में नहीं हैं जो abc.txt में हैं

मैं यह कैसे कर सकता हूँ ?

जवाबों:


19

यदि आपका लक्ष्य आम या असामान्य रेखाओं को ढूंढना है, तो commक्या मेरी आज्ञा यहाँ होगी।

यह दो फाइलों की तुलना करता है और तीन कॉलम दिखाता है- लाइनें जो कि फ़ाइल 1 के लिए अद्वितीय हैं, लाइनें जो कि फ़ाइल 2 के लिए अद्वितीय हैं और क्रमशः दोनों फ़ाइलों में दिखाई देने वाली लाइनें। आप इसे किसी भी आउटपुट को दबाने के लिए इसे झंडे पास कर सकते हैं। Eg comm -1 file1 file2पहले कॉलम को दबाएगा, फ़ाइल 1 के लिए अद्वितीय चीजें। comm -12 file1 file2दोनों फाइलों में केवल चीजें दिखाएगा।

एक बड़ा चेतावनी है: इनपुट को क्रमबद्ध किया जाना चाहिए। हम इसके आसपास काम कर सकते हैं।

यह आपको abc में वह सब कुछ दिखाएगा जो mno में नहीं है:

comm -23 <(sort abc.txt) <(sort mno.txt)

और आप wc -lएक गिनती प्राप्त करने के लिए उसे पाइप कर सकते हैं ।


मेरे साथ जाने का कारण यह commहै कि एक बार फाइलें छँट जाने के बाद, साइड-बाय-साइड तुलना कम्प्यूटेशनल रूप से वास्तव में सरल होती है। यदि आप इनमें से लाखों के साथ काम कर रहे हैं, तो इससे फर्क पड़ेगा।

यह कुछ नकली फाइलों के साथ प्रदर्शित किया जा सकता है। मेरे पास एक काफी तेज़ कंप्यूटर है इसलिए दृष्टिकोणों के बीच अंतर दिखाने के लिए, मुझे एक विशाल नमूना सेट की आवश्यकता है। मैं प्रति फ़ाइल 10 मिलियन 10-चार तार गया हूँ।

$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt

$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s

$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s

$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s

$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt  mno.txt | wc -l
... 0m12.161s

छँटाई वह है जो मेरा अधिकांश समय लेती है। यदि हम दिखावा करते हैं कि abc.txt स्थिर है, तो हम इसे पूर्व-क्रमबद्ध कर सकते हैं और इससे भविष्य की तुलना बहुत तेज़ी से होती है:

$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s

आप इन्हें देख सकते हैं और कुछ सेकंड के लिए अप्रासंगिक मान सकते हैं, लेकिन मुझे यह उजागर करना होगा कि ये एक उच्च अंत मशीन पर चल रहे हैं। यदि आप इसे (उदाहरण के लिए) रास्पबेरी पाई 3 पर करना चाहते हैं, तो आप बहुत धीमी टर्नआर्ड्स देख रहे होंगे और अंतर एक बिंदु तक बढ़ जाएगा जो वास्तव में मायने रखता है।


7

एक सूची प्राप्त करने के लिए:

grep -Fwf abc.txt mno.txt

यह आपको कुछ इसी तरह देता है:

abcd
abcd
zef

यदि आप केवल एक अद्वितीय सूची प्राप्त करना चाहते हैं तो इसका उपयोग करें जैसे:

grep -Fwf abc.txt mno.txt | sort | uniq

और मायने रखने के लिए:

grep -Fcwv -f abc.txt mno.txt

  • -F का अर्थ है: नियमित अभिव्यक्तियों के बजाय निश्चित स्ट्रिंग की सूची के रूप में PATTERN की व्याख्या करें।
  • -fFILE से पैटर्न प्राप्त करें जो होने जा रहा है abc.txt
  • हम mno.txtपैटर्न के लिए देखो
  • -c माचिस की संख्या गिनें
  • -wकेवल "पूरे शब्द" के लिए देखें: मेल खाने वाला विकल्प या तो पंक्ति की शुरुआत में होना चाहिए, या गैर-शब्द घटक वर्ण से पहले होना चाहिए। इसी तरह, यह या तो पंक्ति के अंत में होना चाहिए या एक गैर-शब्द घटक चरित्र के बाद होना चाहिए। शब्द-घटक वर्ण अक्षर, अंक और अंडरस्कोर हैं।
  • -v खोज को उलट दें

1
यदि ओपी गैर मैचों की गिनती चाहता है , तो क्या उसे अधिक पसंद नहीं किया जाना चाहिए ? grep -cxvFf abc.txt mno.txt
स्टीलड्राइवर

अभी-अभी देखा: D ... आपका हमेशा मुझे बचाने के लिए यहाँ: D
Ravexina

FYI करें fgrep, egrepवैकल्पिक रूप से माना जाता है कि (के पक्ष में grep -F, grep -E- हालांकि मुझे यकीन नहीं है कि किसी को भी विश्वास है कि वे कभी भी चले जाएंगे
Steeldriver

क्या उपयोग करते -xसमय उपयोग करना आवश्यक है -F?
रवेक्सिना

1
यह निर्भर करता है कि ओपी वास्तव में क्या गिनना चाहता है - उदाहरण के लिए यदि mno.txt में abcdefमैच या नॉन-मैच के रूप में गिनती होनी चाहिए abcd?
स्टीलड्राइवर

3

हम दो फ़ाइलों को पास करके काम करने के लिए awk का उपयोग कर सकते हैं, पहले पैटर्न फ़ाइल, फिर वह फ़ाइल जिसे हम जांचना चाहते हैं। जब हम पहली फ़ाइल पढ़ रहे होते हैं, तो हम जानते हैं कि NR==FNRऔर उस समय हम सरणी में लाइनें पढ़ सकते हैं। जब NR!=FNRहम जाँचते हैं कि क्या ऐसी लाइन के लिए सरणी सेट है।

$ cat abc.txt                                                      
abcd
xyz
pqrs
$ cat mno.txt                                                      
zzon
xyz
mkno
abcd
$ awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt  mno.txt         
xyz
abcd

इसके विपरीत, हम उन पंक्तियों को मुद्रित करने के लिए पैटर्न को नकार सकते हैं जो अंदर नहीं हैं abc.txt

$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt  mno.txt       
zzon
mkno

और हम उन हम उपयोग कर सकते हैं की गिनती प्रिंट करना चाहते हैं, तो sortऔर wc:

$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt  mno.txt | sort -u | wc -l         
2

मुझे लगता है कि आपके पास यह गलत तरीका है। जहां तक ​​मैं इस प्रश्न को समझता हूं, ओपी abc.txt- ( mno.txtजो है ) के सेट अंतर के आकार (आकार) की गणना करना चाहता है {xyz, pqrs}
डेविड फ़ॉस्टर

2

यदि दोनों में से कोई भी शब्द सूचिबद्ध नहीं है, तो सामान्य शब्दों को याद रखने के लिए एक कुशल सेट डेटा संरचना का उपयोग करना तेज़ होगा।

अजगर

#!/usr/bin/env python3
import sys

with open(sys.argv[1]) as minuend_file:
    minuend = frozenset(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
    subtrahend = frozenset(map(str.rstrip, subtrahend_file))

difference = minuend - subtrahend
#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference

उपयोग:

python3 set-difference.py abc.txt mno.txt

अजगर (अधिक कुशल)

यदि आप मध्यस्थ भंडारण के लिए थोड़ी मेमोरी बचाना चाहते हैं और समय चलाना चाहते हैं तो आप प्रोग्राम को समझने के लिए इस थोड़ी अधिक मुश्किल का उपयोग कर सकते हैं:

#!/usr/bin/env python3
import sys

with open(sys.argv[1]) as minuend_file:
    minuend = set(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
    subtrahend = map(str.rstrip, subtrahend_file)
    minuend.difference_update(subtrahend)
    difference = minuend
    del minuend

#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference

प्रदर्शन

दिए गए abc.txtऔर mno.txt10 यादृच्छिक ASCII अंक वर्णों की 1 mio अनसुलझी पंक्तियों के साथ प्रत्येक (सेट-अप के लिए ओली का उत्तर देखें):

$ time python3 set-difference.py abc.txt mno.txt
user    0m10.453s

बनाम

$ export LC_COLLATE=C
$ time sort abc.txt > abc_sorted.txt
user    0m10.652s
$ time sort mno.txt > mno_sorted.txt
user    0m10.767s
$ time comm -23 abc_sorted.txt mno_sorted.txt | wc -l
9989882
user    0m1.600s

कुल: 23 सेकंड

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