यह वही है जो awk के लिए डिज़ाइन किया गया था:
$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|
व्याख्या
-F'|'
: के लिए क्षेत्र विभाजक सेट करता है |
।
NR==FNR
: एनआर वर्तमान इनपुट लाइन नंबर और एफएनआर वर्तमान फाइल की लाइन नंबर है। दोनों केवल 1 फ़ाइल पढ़ने के दौरान समान होंगे।
c[$1$2]++; next
: यदि यह पहली फ़ाइल है, तो c
सरणी में पहले दो फ़ील्ड सहेजें । फिर, अगली पंक्ति पर जाएं ताकि यह केवल 1 फ़ाइल पर लागू हो।
c[$1$2]>0
: दूसरे ब्लॉक को केवल तभी निष्पादित किया जाएगा यदि यह दूसरी फ़ाइल है इसलिए हम जांचते हैं कि क्या इस फ़ाइल के फ़ील्ड 1 और 2 पहले ही देखे जा चुके हैं ( c[$1$2]>0
) और यदि वे गए हैं, तो हम लाइन प्रिंट करते हैं। में awk
, डिफ़ॉल्ट क्रिया लाइन को प्रिंट करने के लिए है इसलिए यदि c[$1$2]>0
यह सत्य है, तो लाइन प्रिंट की जाएगी।
वैकल्पिक रूप से, जब से आपने पर्ल के साथ टैग किया है:
perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1
व्याख्या
पहली पंक्ति खुल जाएगी file2
, 2 डी तक सब कुछ पढ़ें |
( .+?\|[^|]+
) और हैश $&
में ( अंतिम मैच ऑपरेटर का परिणाम है ) सहेजें %k
।
दूसरी पंक्ति फ़ाइल 1 को संसाधित करती है, पहली दो कॉलम को निकालने के लिए उसी रेगेक्स का उपयोग करती है और यदि उन कॉलम को %k
हैश में परिभाषित किया जाता है तो लाइन को प्रिंट करें ।
उपरोक्त दोनों दृष्टिकोणों को फ़ाइल 2 के पहले कॉलम को मेमोरी में रखने की आवश्यकता होगी। यह समस्या नहीं होनी चाहिए यदि आपके पास केवल कुछ सौ हजार लाइनें हैं, लेकिन यदि यह है, तो आप कुछ ऐसा कर सकते हैं
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
लेकिन वह धीमा होगा।