2010-12-28 9 views
85

मैं फ़ाइल 1 के साथ फ़ाइल 1 की तुलना करना चाहता हूं और फ़ाइल 3 जेनरेट करना चाहता हूं जिसमें फ़ाइल 1 में लाइनें हैं जो फ़ाइल 2 में मौजूद नहीं हैं।लाइन से दो फाइलों की तुलना करें और दूसरी फ़ाइल में अंतर उत्पन्न करें

+7

स्पष्ट सवाल, लेकिन उसे स्वीकार उत्तर को श्रेष्ठ उत्तर नहीं है। –

+0

मैंने diff की कोशिश की लेकिन यह कुछ संख्याओं और अन्य प्रतीकों को अलग-अलग लाइनों के सामने उत्पन्न करता है जो फ़ाइलों की तुलना करना मेरे लिए मुश्किल बनाता है। – Sun

उत्तर

158

diff (1) उत्तर नहीं है, लेकिन कम (1) है।

NAME 
     comm - compare two sorted files line by line 

SYNOPSIS 
     comm [OPTION]... FILE1 FILE2 

... 

     -1  suppress lines unique to FILE1 

     -2  suppress lines unique to FILE2 

     -3  suppress lines that appear in both files 

तो

comm -2 -3 file1 file2 > file3 

इनपुट फ़ाइलों को क्रमबद्ध किया जाना चाहिए। यदि वे नहीं हैं, तो उन्हें पहले क्रमबद्ध करें। यह एक अस्थायी फ़ाइल के साथ किया जा सकता है, या ...

comm -2 -3 <(sort file1) <(sort file2) > file3 

प्रदान किया गया है कि आपका खोल प्रक्रिया प्रतिस्थापन (बैश करता है) का समर्थन करता है।

+0

मूल प्रश्नकर्ता के समान प्रश्न था, लेकिन यह वही है जो मुझे चाहिए था। धन्यवाद! – zarose

+1

याद रखें कि दो फाइलों को सॉर्ट किया जाना चाहिए और अद्वितीय – andy

+5

है आप विकल्पों को एक साथ समूहित कर सकते हैं: 'comm -23' –

38

यूनिक्स उपयोगिता diff बिल्कुल इस उद्देश्य के लिए है।

$ diff -u file1 file2 > file3 

मैनुअल और विकल्प, विभिन्न उत्पादन प्रारूपों के लिए इंटरनेट, आदि

+7

वह नौकरी का अनुरोध नहीं करता है; यह अन्य उत्तरों में सुझाए गए कमांडलाइन स्विच के उपयोग के साथ भी अतिरिक्त पात्रों का एक समूह डालता है। – xenocyon

2

उपयोग Diff उपयोगिता और निकालने केवल लाइनों शुरू कर देखें < साथ उत्पादन

6
कभी कभी

diff में उपयोगिता है आपको चाहिए, लेकिन कभी-कभी join अधिक उपयुक्त है। फ़ाइलों को पूर्व-क्रमबद्ध करने की आवश्यकता है या, यदि आप एक खोल का उपयोग कर रहे हैं जो प्रक्रिया प्रतिस्थापन जैसे बैश, केश या जेएसएच का समर्थन करता है, तो आप फ्लाई पर सॉर्ट कर सकते हैं।

join -v 1 <(sort file1) <(sort file2) 
14

इस पर विचार करें:
फ़ाइल a.txt:

abcd 
efgh 

फ़ाइल b.txt:

diff -a --suppress-common-lines -y a.txt b.txt 

:

abcd 

आप के साथ अंतर पा सकते हैं आउटपुट डब्ल्यू बीमार:

efgh 

आप कोई आउटपुट फ़ाइल (c.txt) में उत्पादन redirict का उपयोग कर सकते हैं:

diff -a --suppress-common-lines -y a.txt b.txt > c.txt 

यह आपके सवाल का जवाब देगा:

"... जो फ़ाइल 1 में लाइनें हैं जो फ़ाइल 2 में मौजूद नहीं हैं। "

+2

इस जवाब देने के लिए दो सीमाओं के होते हैं: (1) यह केवल कम लाइनों के लिए काम करता है (कम से कम 80 वर्ण डिफ़ॉल्ट रूप से, हालांकि इस संशोधित किया जा सकता है) और, अधिक महत्वपूर्ण, (2) यह एक "<" के अंत में जोड़ने प्रत्येक पंक्ति जिसे किसी अन्य प्रोग्राम से दूर ले जाना चाहिए (उदाहरण के लिए awk, sed)। – sergut

+0

कई मामलों में, आप भी 'उपयोग करने के लिए -d', जो कर देगा चाहता हूँ' छोटी संभव diff खोजने के लिए अपने सबसे अच्छे रूप diff'do। '-i',' -E', '-w',' -B' और '--suppress-blank-blank' कभी-कभी उपयोगी भी हो सकता है, हालांकि हमेशा नहीं।यदि आपको नहीं पता कि आपके उपयोग के मामले में क्या फिट बैठता है, तो पहले 'diff --help'' आज़माएं (जो आम तौर पर एक अच्छा विचार है जब आप नहीं जानते कि कमांड क्या कर सकता है)। –

+0

इसके अलावा, --line-format =% L का उपयोग करके, आप किसी भी अतिरिक्त वर्ण उत्पन्न करने से भिन्न रहते हैं (कम से कम, सहायता कहती है कि यह इस तरह काम करती है, फिर भी इसे आजमाएं)। –

2

sdiff file1 file2 

प्रयास करें यह ususally मेरे लिए ज्यादातर मामलों में काफी बेहतर काम करता है। यदि लाइनों का क्रम महत्वपूर्ण नहीं है (उदाहरण के लिए कुछ टेक्स्ट कॉन्फ़िगरेशन फ़ाइलें), तो आप फ़ाइलों को पहले सॉर्ट करना चाहेंगे।

उदाहरण के लिए

,

sdiff -w 185 file1.cfg file2.cfg 
+1

अच्छी उपयोगिता! मुझे प्यार है कि यह अलग-अलग लाइनों को कैसे चिह्नित करता है। कॉन्फ़िगरेशन की तुलना करना अधिक आसान बनाता है। यह एक साथ एक घातक कॉम्बो है (उदा। 'Sdiff <(sort file1) <(sort file2) ') – jmagnusson

2

कई पहले से ही जवाब है, लेकिन उनमें से कोई भी सही IMHO। थानाटोस का जवाब प्रति पंक्ति कुछ अतिरिक्त पात्रों को छोड़ देता है और सोरपिगल के जवाब को फ़ाइलों को सॉर्ट या पूर्व-क्रमबद्ध करने की आवश्यकता होती है, जो सभी परिस्थितियों में पर्याप्त नहीं हो सकती है।

मुझे लगता है कि लाइनों है कि विभिन्न और कुछ नहीं (बिना किसी अतिरिक्त वर्ण, कोई फिर से आदेश) कर रहे हैं होने का सबसे अच्छा तरीका है diff, grep, और awk (या समान) का एक संयोजन है।

लाइनों किसी भी "<", शामिल नहीं हैं एक छोटी एक लाइनर हो सकता है:

diff urls.txt* | grep "<" | sed 's/< //g' 

लेकिन यह है कि (कम से कम, अंतरिक्ष) लाइनों से "<" के प्रत्येक उदाहरण निकाल देंगे, जो हमेशा ठीक नहीं है (उदाहरण के लिए स्रोत कोड)। है, तो, तो

diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' 

यह एक लाइनर डिफ दोनों फ़ाइलों भिन्नता की एड शैली उत्पादन बाहर फिल्टर को हटा अनुगामी "<" कि diff कहते हैं: सबसे सुरक्षित विकल्प awk उपयोग करने के लिए है। यह तब भी काम करता है जब रेखाओं में कुछ "<" स्वयं होता है।

+1

कमांड को सॉर्टिंग (नए संस्करणों में) की आवश्यकता नहीं है - बस - नोचेक-ऑर्डर का उपयोग करें। सीएलआई – ak5

2

आप coreutils के साथ इस का समाधान करने की जरूरत है स्वीकार किए जाते हैं जवाब अच्छा है:

comm -23 <(sort file1) <(sort file2) > file3 

तुम भी sd (धारा अंतर) का उपयोग कर सकते है, जो छँटाई और न ही प्रक्रिया प्रतिस्थापन की आवश्यकता नहीं है और जैसे अनंत धाराओं का समर्थन करता है, इसलिए:

cat file1 | sd 'cat file2' > file3 

शायद इस उदाहरण पर इतना लाभ नहीं है, लेकिन फिर भी इसे मानें; कुछ मामलों में आप comm है और न ही grep -F है और न ही diff उपयोग करने में सक्षम नहीं होगा।

यहाँ एक blogpost मैं टर्मिनल, जो एसडी का परिचय पर धाराओं diffing के बारे में लिखा है।

1
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt 

मैंने इस धागे में लगभग सभी उत्तरों की कोशिश की, लेकिन कोई भी पूरा नहीं हुआ। एक के ऊपर कुछ निशान के बाद मेरे लिए काम किया। diff आपको कुछ अवांछित विशेष charas के साथ अंतर देगा। जहां आप वास्तविक अंतर रेखाएं '>' से शुरू होती हैं। तो अगले कदम '>' के साथ शुरू होता है और के साथ एक ही हटाने के द्वारा पीछा किया sedग्रेप लाइनों के लिए है।

+0

से सीएसवी में हेरफेर करते समय मैं इसका बहुत उपयोग करता हूं यह एक बुरा विचार है। आपको '<' से शुरू होने वाली लाइनों को संशोधित करने की भी आवश्यकता होगी। यदि आप इनपुट फ़ाइलों के क्रम को स्वैप करते हैं तो आप इसे देखेंगे। यहां तक ​​कि यदि आपने ऐसा किया है तो आप अधिक sed का उपयोग करके 'grep' को छोड़ना चाहते हैं:' diff a1 a2 | sed '/>/s ///' 'यह अभी भी सही स्थिति में '>' या '<' वाली रेखाएं तोड़ सकता है और ** अभी भी ** रेखा संख्याओं का वर्णन करने वाली अतिरिक्त पंक्तियां छोड़ देता है। यदि आप इस दृष्टिकोण को आजमा सकते हैं तो बेहतर तरीका होगा: 'diff -C0 a1 a2 | sed -ne '/^[+ -]/s /^..// p''। – Sorpigal

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