आप GNU diff
आउटपुट में पुरानी / नई / अपरिवर्तित लाइनों के प्रारूपण को नियंत्रित करके इसे प्राप्त कर सकते हैं :
diff --new-line-format="" --unchanged-line-format="" file1 file2
इसके लिए काम करने के लिए इनपुट फ़ाइलों को सॉर्ट किया जाना चाहिए । के साथ bash
और zsh
) आप प्रक्रिया स्थानापन्न के साथ इन-प्लेस को सॉर्ट कर सकते हैं <( )
:
diff --new-line-format="" --unchanged-line-format="" <(sort file1) <(sort file2)
उपरोक्त नई और अपरिवर्तित लाइनें दबा दी गई हैं, इसलिए केवल परिवर्तित (यानी आपके मामले में हटाए गए लाइनें) आउटपुट हैं। तुम भी कुछ प्रयोग कर सकते हैं diff
विकल्प है कि अन्य समाधान नहीं करते हैं, इस तरह के रूप -i
मामले, या विभिन्न खाली स्थान के विकल्प (अनदेखी करने के लिए -E
, -b
, -v
आदि) में कम सख्त मिलान के लिए।
व्याख्या
विकल्प --new-line-format
, --old-line-format
और --unchanged-line-format
आप प्रारूप विनिर्देशकों के diff
समान अंतर को printf
प्रारूपित करने के तरीके को नियंत्रित करते हैं । ये विकल्प क्रमशः नए (जोड़े गए), पुराने (हटाए गए) और अपरिवर्तित लाइनों को प्रारूपित करते हैं। एक को खाली सेट करना "" उस तरह के लाइन के आउटपुट को रोकता है।
यदि आप एकीकृत अंतर प्रारूप से परिचित हैं , तो आप इसे आंशिक रूप से फिर से बना सकते हैं:
diff --old-line-format="-%L" --unchanged-line-format=" %L" \
--new-line-format="+%L" file1 file2
%L
विनिर्देशक प्रश्न में लाइन है, और हम साथ "+" "प्रत्येक उपसर्ग -" या "", की तरह diff -u
(ध्यान दें कि यह केवल outputs मतभेद, यह अभाव है ---
+++
और @@
लाइनों प्रत्येक वर्गीकृत किया परिवर्तन के शीर्ष पर)। आप इसका उपयोग अन्य उपयोगी चीजों को करने के लिए भी कर सकते हैं जैसे संख्या प्रत्येक पंक्ति के साथ %dn
।
diff
विधि (अन्य सुझावों के साथ comm
और join
) के साथ ही उम्मीद उत्पादन का उत्पादन क्रमबद्ध , इनपुट ही आप उपयोग कर सकते हैं <(sort ...)
जगह में सॉर्ट करने के लिए। यहाँ एक सरल awk
(nawk) स्क्रिप्ट है (लिपियों से जुड़े-कोनोकोस्बॉक्स के उत्तर में लिपियों से प्रेरित) जो मनमाने ढंग से ऑर्डर की गई इनपुट फ़ाइलों को स्वीकार करती है, और फ़ाइल 1 में होने वाले क्रम में लापता लाइनों को आउटपुट करती है।
# output lines in file1 that are not in file2
BEGIN { FS="" } # preserve whitespace
(NR==FNR) { ll1[FNR]=$0; nl1=FNR; } # file1, index by lineno
(NR!=FNR) { ss2[$0]++; } # file2, index by string
END {
for (ll=1; ll<=nl1; ll++) if (!(ll1[ll] in ss2)) print ll1[ll]
}
यह लाइन-संख्या अनुक्रमित सरणी में लाइन द्वारा फ़ाइल 1 लाइन की संपूर्ण सामग्री को संग्रहीत करता है ll1[]
, और लाइन-सामग्री अनुक्रमित साहचर्य सरणी में लाइन द्वारा फ़ाइल 2 लाइन की संपूर्ण सामग्री ss2[]
। दोनों फाइलों को पढ़ने के बाद, यह निर्धारित करने के लिए कि फाइल 1 में लाइन फाइल 2 में मौजूद है या नहीं, ऑपरेटर को इटरेट ll1
करें और उसका उपयोग करें in
। (यह diff
डुप्लिकेट होने पर विधि के लिए अलग आउटपुट होगा।)
इस घटना में कि फाइलें पर्याप्त रूप से बड़ी हैं, उन दोनों को संग्रहीत करने से मेमोरी समस्या होती है, आप केवल फ़ाइल 1 को स्टोर करके मेमोरी के लिए सीपीयू का व्यापार कर सकते हैं और फाइल के पढ़ने के साथ ही मैच को हटा सकते हैं।
BEGIN { FS="" }
(NR==FNR) { # file1, index by lineno and string
ll1[FNR]=$0; ss1[$0]=FNR; nl1=FNR;
}
(NR!=FNR) { # file2
if ($0 in ss1) { delete ll1[ss1[$0]]; delete ss1[$0]; }
}
END {
for (ll=1; ll<=nl1; ll++) if (ll in ll1) print ll1[ll]
}
उपर्युक्त फ़ाइल संख्या की पूरी सामग्री को दो सरणियों में संग्रहीत करता है, एक पंक्ति संख्या ll1[]
द्वारा अनुक्रमित, एक पंक्ति सामग्री द्वारा अनुक्रमित ss1[]
। तब जैसा कि file2 पढ़ा जाता है, प्रत्येक मिलान रेखा से ll1[]
और हटा दिया जाता है ss1[]
। अंत में फ़ाइल 1 से शेष लाइनें आउटपुट हैं, मूल क्रम को संरक्षित करते हुए।
इस स्थिति में, बताई गई समस्या के साथ, आप GNU का उपयोग करके विभाजित और जीत भी सकते हैं split
(फ़िल्टरिंग एक GNU एक्सटेंशन है), फ़ाइल 1 के विखंडन के साथ बार-बार चलता है और फ़ाइल 2 को पूरी तरह से पढ़ता है:
split -l 20000 --filter='gawk -f linesnotin.awk - file2' < file1
कमांड लाइन पर -
अर्थ के उपयोग और प्लेसमेंट stdin
पर ध्यान दें gawk
। यह split
20000 लाइन प्रति-आह्वान के अंशों में फ़ाइल 1 से प्रदान किया गया है।
गैर जीएनयू सिस्टम पर उपयोगकर्ताओं के लिए, वहाँ है लगभग निश्चित रूप से एक GNU coreutils पैकेज आप प्राप्त कर सकते हैं के हिस्से के रूप पर OSX सहित एप्पल Xcode उपकरण जो जीएनयू प्रदान करता है diff
, awk
है, हालांकि केवल एक POSIX / बीएसडी split
के बजाय एक जीएनयू संस्करण।
awk 'NR==FNR{a[$0];next}!($0 in a)' file2 file1 > out.txt