मेरे पास तीन फाइलें हैं, प्रत्येक में एक आईडी और एक मूल्य है।

sdt5z@fir-s:~/test$ ls
a.txt  b.txt  c.txt
sdt5z@fir-s:~/test$ cat a.txt 
id1 1
id2 2
id3 3
sdt5z@fir-s:~/test$ cat b.txt 
id1 4
id2 5
id3 6
sdt5z@fir-s:~/test$ cat c.txt 
id1 7
id2 8
id3 9

मैं एक ऐसी फाइल बनाना चाहता हूं जो इस तरह दिखती है ...

id1 1 4 7
id2 2 5 8
id3 3 6 9

... अधिमानतः एकल कमांड का उपयोग करना।

मुझे जॉइन और पेस्ट कमांड के बारे में पता है। पेस्ट हर बार आईडी कॉलम की नकल करेगा:

sdt5z@fir-s:~/test$ paste a.txt b.txt c.txt 
id1 1   id1 4   id1 7
id2 2   id2 5   id2 8
id3 3   id3 6   id3 9

जॉइन अच्छा काम करता है, लेकिन एक बार में केवल दो फाइलों के लिए:

sdt5z@fir-s:~/test$ join a.txt b.txt 
id1 1 4
id2 2 5
id3 3 6
sdt5z@fir-s:~/test$ join a.txt b.txt c.txt 
join: extra operand `c.txt'
Try `join --help' for more information.

मुझे यह भी पता है कि पेस्ट "-" का उपयोग करके एसटीडीआईएन को तर्कों में से एक के रूप में ले सकता है। उदाहरण के लिए, मैं ज्वाइन कमांड का उपयोग करके दोहरा सकता हूं:

sdt5z@fir-s:~/test$ cut -f2 b.txt | paste a.txt -
id1 1   4
id2 2   5
id3 3   6

लेकिन मुझे अभी भी यकीन नहीं है कि तीन फाइलों को समायोजित करने के लिए इसे कैसे संशोधित किया जाए।

चूंकि मैं इसे एक पर्ल स्क्रिप्ट के अंदर कर रहा हूं, मुझे पता है कि मैं इसे फ़ोरैच लूप के अंदर डालने जैसा कुछ कर सकता हूं, कुछ फ़ाइल 1 फ़ाइल 2> tmp1 में शामिल हों, tmp1 फ़ाइल 3> tmp2, आदि में शामिल हों। लेकिन यह गन्दा हो जाता है, और मैं चाहूंगा एक-लाइनर के साथ ऐसा करने के लिए।

4
Stephen Turner 9 फरवरी 2012, 18:43

4 जवाब

सबसे बढ़िया उत्तर

join a.txt b.txt|join - c.txt

पर्याप्त होना चाहिए

12
Sergey Benner 10 फरवरी 2012, 23:18

चूंकि आप इसे एक पर्ल स्क्रिप्ट के अंदर कर रहे हैं, क्या कोई विशिष्ट कारण है कि आप पर्ल में काम नहीं कर रहे हैं, जैसा कि शेल में स्पॉनिंग के विपरीत है?

कुछ इस तरह (परीक्षण नहीं किया गया! चेतावनी एम्प्टर):

use File::Slurp; # Slurp the files in if they aren't too big
my @files = qw(a.txt b.txt c.txt);
my %file_data = map ($_ => [ read_file($_) ] ) @files;
my @id_orders;
my %data = ();
my $first_file = 1;
foreach my $file (@files) {
    foreach my $line (@{ $file_data{$file} }) {
        my ($id, $value) = split(/\s+/, $line);
        push @id_orders, $id if $first_file;
        $data{$id} ||= [];
        push @{ $data{$id} }, $value;
    }
    $first_file = 0;
}
foreach my $id (@id_orders) {
    print "$d " . join(" ", @{ $data{$id} }) . "\n";
}
1
DVK 9 फरवरी 2012, 19:01

perl -lanE'$h{$F[0]} .= " $F[1]" END{say $_.$h{$_} foreach keys %h}' *.txt

काम करना चाहिए, इसका परीक्षण नहीं कर सकता क्योंकि मैं अपने मोबाइल से उत्तर दे रहा हूं। यदि आप foreach और keys के बीच sort डालते हैं, तो आप आउटपुट को सॉर्ट भी कर सकते हैं।

0
Patrick Seebauer 9 फरवरी 2012, 20:33
pr -m -t -s\  file1.txt file2.txt|gawk '{print $1"\t"$2"\t"$3"\t"$4}'> finalfile.txt

फ़ाइल 1 और फ़ाइल 2 को ध्यान में रखते हुए 2 कॉलम हैं और 1 और 2 फ़ाइल 1 से कॉलम का प्रतिनिधित्व करते हैं और 3 और 4 फ़ाइल 2 से कॉलम का प्रतिनिधित्व करते हैं।

आप प्रत्येक फ़ाइल से किसी भी कॉलम को इस तरह से प्रिंट भी कर सकते हैं और यह इनपुट के रूप में कितनी भी फाइलें ले लेगा। उदाहरण के लिए यदि आपके फ़ाइल1 में 5 कॉलम हैं, तो $6 फ़ाइल2 का पहला कॉलम होगा।

0
Ren 16 अप्रैल 2013, 13:22