Awk के साथ दो फाइलों को मिलाएं


9

File1.txt

item1   carA
item2   carB
item3   carC
item4   platD
item5   carE

File2.txt

carA  platA
carB  platB
carC  platC
carE  platE

चाहता था उत्पादन:

item1   platA
item2   platB
item3   platC
item4   platD
item5   platE

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

जवाबों:


11

नीचे दिया गया उत्तर कुछ प्रासंगिक संशोधनों के साथ SO में समान Q & A पर आधारित है :

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($2 in dict) ? dict[$2] : $2}1' file2.txt file1.txt 
item1 platA
item2 platB
item3 platC
item4 platD
item5 platE

सूचकांक के साथ हैश-मैप बनाने और इसे शब्दकोश के रूप में उपयोग करने का विचार है।

आपकी टिप्पणी में पूछे गए 2 वें प्रश्न के लिए ( यदि दूसरा कॉलम file1.txtछठा कॉलम होगा तो क्या बदला जाना चाहिए ):

यदि इनपुट फ़ाइल इस प्रकार होगी file1b.txt:

item1 A5 B C D carA
item2 A4 1 2 3 carB
item3 A3 2 3 4 carC
item4 A2 4 5 6 platD
item5 A1 7 8 9 carE

निम्न आदेश यह करेंगे:

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($6 in dict) ? dict[$6] : $6;$3="";$4="";$5="";$6=""}1' file2.txt file1b.txt 
item1 platA    
item2 platB    
item3 platC    
item4 platD    
item5 platE    

1
@pawana - मैंने अपना जवाब अपडेट में आपके दूसरे प्रश्न को हल करने के लिए भी अपडेट किया है। यदि मैंने आपके प्रश्न का उत्तर दिया है तो कृपया इसे स्वीकार करें
यार्न

6

मुझे पता है आपने कहा था awk, लेकिन joinइस उद्देश्य के लिए एक आदेश है ...

{
  join -o 1.1,2.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt)     
  join -v 1 -o 1.1,1.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt) 
} | sort -k 1

joinयदि यह इस पंक्ति के लिए नहीं था तो यह पहली कमांड के साथ पर्याप्त होगा :

item4   platD

कमांड मूल रूप से कहती है: पहली फाइल के दूसरे कॉलम ( -1 2), और दूसरी फाइल के पहले कॉलम ( ) के आधार पर ज्वाइन करें, और पहली फाइल के पहले कॉलम और दूसरी फाइल के दूसरे कॉलम ( -2 1) को आउटपुट करें -o 1.1,2.2। यह केवल उन पंक्तियों को दिखाता है जो युग्मित हैं। दूसरी ज्वाइन कमांड लगभग एक ही बात कहती है, लेकिन यह पहली फाइल से लाइनों को दिखाने के लिए कहती है जिसे जोड़ा नहीं जा सकता ( -v 1), और पहली फाइल के पहले कॉलम और दूसरे फाइल के पहले कॉलम ( ) को आउटपुट करता है -o 1.1,1.2। फिर हम दोनों के आउटपुट को संयुक्त करते हैं। sort -k 1पहला कॉलम के sort -k 2आधार पर सॉर्ट करें और दूसरे के आधार पर सॉर्ट करने का मतलब है। इसमें शामिल होने से पहले फ़ाइलों को ज्वाइंट कॉलम के आधार पर क्रमबद्ध करना महत्वपूर्ण है join

अब, मैंने दो बार छंटनी लिखी, क्योंकि मैं अपनी निर्देशिकाओं को फाइलों के साथ लिटाना पसंद नहीं करता अगर मैं इसकी मदद कर सकता / सकती हूं। हालांकि, जैसे डेविड फ़ॉस्टर ने कहा, फ़ाइलों के आकार के आधार पर, आप फ़ाइलों को क्रमबद्ध करना चाहते हैं और उन्हें बचाने के लिए पहले प्रत्येक दो बार सॉर्ट करने के लिए इंतजार न करें। आकारों का विचार देने के लिए, मेरे कंप्यूटर पर 1 मिलियन और 10 मिलियन लाइनों को छांटने का समय यहां दिया गया है:

$ ruby -e '(1..1000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 1million.txt 
$ ruby -e '(1..10000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 10million.txt 
$ head 10million.txt 
item530284   plat530284
item7946579   plat7946579
item1521735   plat1521735
item9762844   plat9762844
item2289811   plat2289811
item6878181   plat6878181
item7957075   plat7957075
item2527811   plat2527811
item5940907   plat5940907
item3289494   plat3289494
$ TIMEFORMAT=%E
$ time sort 1million.txt >/dev/null
1.547
$ time sort 10million.txt >/dev/null
19.187

यह 1 मिलियन लाइनों के लिए 1.5 सेकंड और 10 मिलियन लाइनों के लिए 19 सेकंड है।


इस मामले में (अस्थायी) इंटरमीडिएट फ़ाइलों में सॉर्ट किए गए इनपुट डेटा को संग्रहीत करना बेहतर होगा क्योंकि सॉर्टिंग गैर-तुच्छ आकार के डेटा सेट के लिए काफी लंबा लेता है। अन्यथा +1।
डेविड फ़ॉस्टर

@ डेविड यह एक अच्छा बिंदु है। व्यक्तिगत रूप से, मैं वास्तव में मध्यवर्ती फाइलें बनाने के लिए पसंद नहीं करता, लेकिन मैं लंबे समय तक चलने वाली प्रक्रियाओं के साथ भी अधीर हूं। मैंने सोचा कि "तुच्छ आकार" क्या होगा, और इसलिए मैंने एक छोटा बेंचमार्क बनाया, और इसे आपके सुझाव के साथ उत्तर में जोड़ दिया।
जोएल

क्रमबद्ध करने के लिए 1 mio रिकॉर्ड काफी तेजी से आधुनिक डेस्कटॉप कंप्यूटर पर पर्याप्त है। परिमाण के 2 और 3 आदेशों के साथ और चीजें दिलचस्प होने लगती हैं। किसी भी मामले में (वास्तविक) समय ( %Eसमय प्रारूप में) कम्प्यूटेशनल प्रदर्शन को मापने के लिए कम दिलचस्प नहीं है। उपयोगकर्ता मोड CPU समय ( %Uया बस एक TIMEFORMATपरेशान चर) अधिक सार्थक होगा।
डेविड फ़ॉस्टर

@ डेविड मैं वास्तव में अलग-अलग समय के उपयोग मामलों से परिचित नहीं हूं। यह अधिक दिलचस्प क्यों है? बीता हुआ समय वह है जो उस समय के साथ मेल खाता है जिसका मैं वास्तव में इंतजार कर रहा हूं। 1.5 सेकंड कमांड के लिए, मुझे 4.5 सेकंड मिल रहे हैं %U
जोएल

1
एक ही सिस्टम पर चल रहे अन्य कार्यों पर प्रतीक्षा करने और I / O अनुरोधों को अवरुद्ध करने से व्यतीत समय व्यतीत होता है। (उपयोगकर्ता) CPU समय नहीं है। आमतौर पर जब कम्प्यूटेशनल रूप से बाध्य एल्गोरिदम की गति की तुलना I / O की उपेक्षा करना और अन्य पृष्ठभूमि कार्यों के कारण माप त्रुटियों से बचना चाहता है। महत्वपूर्ण सवाल यह है कि "इस एल्गोरिथ्म को उस डेटा सेट पर कितनी गणना की आवश्यकता है?" इसके बजाय "कंप्यूटर ने अपने सभी कार्यों पर कितना समय बिताया, जबकि वह उस गणना के पूरा होने का इंतजार कर रहा था?"
डेविड फ़ॉस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.