क्या एक फ़ाइल में लाइनें प्राप्त करने का एक उपकरण है जो दूसरे में नहीं है?


110

क्या कोई ऐसा उपकरण है जो ए को फाइल करने वाली लाइनें प्राप्त कर सकता है, लेकिन फाइल बी नहीं है? मैं, उदाहरण के लिए, के साथ एक छोटी सी सरल स्क्रिप्ट बना सकता है, लेकिन अगर ऐसा कुछ पहले से मौजूद है, तो मैं अभी से अपना समय बचाऊंगा।



जवाबों:


159

हाँ। grepटेक्स्ट स्ट्रिंग्स के लिए फ़ाइलों की खोज करने के लिए मानक टूल का उपयोग एक फ़ाइल से दूसरे में सभी पंक्तियों को घटाने के लिए किया जा सकता है।

grep -F -x -v -f fileB fileA

यह फाइलबी में प्रत्येक लाइन को एक पैटर्न के रूप में उपयोग करके काम करता है ( -f fileB) और इसे एक सादे स्ट्रिंग के रूप में मैच करने के लिए (नियमित रेगेक्स नहीं) ( -F) के रूप में मानता है । आप मैच को पूरी लाइन ( -x) पर होने के लिए मजबूर करते हैं और केवल उन लाइनों को प्रिंट करते हैं जो मेल नहीं खाते ( -v)। इसलिए आप फ़ाइलए में उन पंक्तियों को प्रिंट कर रहे हैं जिनमें फ़ाइलबी में कोई भी डेटा नहीं है।

इस समाधान का नकारात्मक पक्ष यह है कि यह लाइन ऑर्डर को ध्यान में नहीं रखता है और यदि आपके इनपुट में अलग-अलग जगहों पर डुप्लिकेट लाइनें हैं, तो आपको वह नहीं मिल सकता है जो आप अपेक्षा करते हैं। इसका समाधान वास्तविक तुलना उपकरण जैसे कि उपयोग करना है diff। आप फ़ाइल में 100% लाइनों पर संदर्भ मूल्य के साथ एक अलग फ़ाइल बनाकर ऐसा कर सकते हैं, फिर इसे केवल उन पंक्तियों के लिए पार्स कर रहे हैं जो फ़ाइल बी को फ़ाइल बी में परिवर्तित करने पर हटा दी जाएगी (ध्यान दें कि यह कमांड भी अंतर को हटा देता है। सही लाइनों को प्राप्त करने के बाद प्रारूपण करना।)

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC

@ inderpreet99 लोअर केस का -uतर्क वास्तव में किसी संख्या के पैरामीटर को तब तक लेता है जब तक कि वह किसी स्थान का अनुसरण नहीं करता है। मेरे पास पहले के तरीके का लाभ यह है कि यह मूल्य के साथ या उसके बिना काम करेगा, इसलिए आप उस उप कमांड रूटीन में कुछ का उपयोग कर सकते हैं जो आउटपुट नहीं लौटा। दूसरी ओर ऊपरी मामले '-यू' के लिए एक तर्क की आवश्यकता होती है।
कालेब

सावधान रहें, grep -f हे (N ^ 2) मेरा मानना ​​है: stackoverflow.com/questions/4780203/…
rogerdpack

1
diffपाइपलाइन इलाज धन्यवाद काम करता है।
फेलिप अल्वारेज़

सॉर्ट की समस्या के लिए खाता करने के लिए, आप आवश्यकतानुसार प्रत्येक फ़ाइल को संसाधित करने के लिए कमांड में प्रक्रिया प्रतिस्थापन का उपयोग कर सकते हैं grep। उदाहरण:grep -F -x -v -f <(sort fileB) <(sort fileA)
टोनी सेसारो

@TonyCesaro यह काम करेगा यदि आपका डेटा सेट विशिष्ट नहीं है और डुप्लिकेट को ध्यान में रखने की आवश्यकता नहीं है। उपयोग करने diffका लाभ यह है कि फ़ाइल में स्थिति को ध्यान में रखा जाता है।
कालेब

57

उत्तर आपके द्वारा तुलना की जा रही फ़ाइलों के प्रकार और प्रारूप पर बहुत अधिक निर्भर करता है।

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

उदाहरण

कहो कि आपके पास निम्न 2 फाइलें हैं:

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

फ़ाइल में वे पंक्तियाँ जो फ़ाइल bमें नहीं हैं a:

$ comm <(sort a) <(sort b) -3
    6

1
उल्लेख करने के लिए +1 comm; दुर्भाग्य से, commसॉर्ट की गई फ़ाइलों की आवश्यकता है
Arcege

11
तो उन्हें सॉर्ट करें? comm <(Sort a) <(Sort b) -1 -2
Sirex

यह कुछ अजीब वाक्य रचना है। <()? यह काम करता है और मैं इसे प्राप्त करता हूं, लेकिन क्या इस अजीबता का कोई नाम है?
mlissner

2
@mlissner <()को प्रोसेस प्रतिस्थापन के रूप में भी जाना जाता है
मिकू

1
commमूल रूप से बेल लैब्स में किसी के द्वारा 1973 में सर्कस लिखा गया था, आरएमएस पर नहीं। आप GNU कार्यान्वयन की बात कर रहे हैं जो बहुत बाद में आया। वर्षों में यूनिक्स उपयोगिताओं के कई अलग-अलग कार्यान्वयन हुए हैं।
स्टीफन चेज़लस

32

से stackoverflow ...

comm -23 file1 file2

-23 उन फ़ाइलों को दबाता है जो दोनों फ़ाइलों में हैं, या केवल फ़ाइल 2 में हैं। फ़ाइलों को क्रमबद्ध किया जाना है (वे आपके उदाहरण में हैं) लेकिन यदि नहीं, तो उन्हें पहले सॉर्ट के माध्यम से पाइप करें ...

मैन पेज यहाँ देखें


यह मेरे लिए किसी कारण से काम नहीं करता ...
Jan

@ क्या आपकी फाइलें क्रमबद्ध हैं? आपने उन्हें कैसे छांटा?
JJS 19

8

ग्रीप और कॉम (सॉर्ट के साथ) तरीके बड़ी फ़ाइलों पर लंबा समय लेते हैं । Stack ओवरफ्लो पर दो फ़ाइलों में से एक के लिए अद्वितीय लाइनों को निकालने के लिए SiegeX और ghostdog74 ने दो महान awk विधियाँ साझा कीं :

$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2

$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2

2
यदि आप विशाल फ़ाइलों के साथ ऐसा कर रहे हैं, तो एक विशाल फ़ाइल को एक सहयोगी सरणी में लोड करने की मेमोरी बाधाएं निषेधात्मक होने जा रही हैं।
चार्ल्स डफी

4

यदि फ़ाइलें बड़ी हैं और आपके पास अपनी प्रविष्टियों के लिए कोई कस्टम ऑर्डर नहीं है, तो grep को बहुत लंबा समय लगता है। एक त्वरित विकल्प होगा

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[file2-file1 परिणाम स्क्रीन, फाइल करने के लिए पाइप आदि]

बदलने के >लिए <विपरीत घटाव प्राप्त होगा।rm 1 2


2

आप vimdiff पर भी विचार कर सकते हैं, यह एक विम एडिटर में फाइलों के बीच के अंतर को उजागर करता है


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