मैं लाइन के आधार पर एक लाइन पर फ़ाइलों को कैसे मर्ज कर सकता हूं?


22

बिल्ली file1

foo
ice
two

बिल्ली file2

bar
cream
hundred

वांछित उत्पादन:

foobar
icecream
twohundred

फ़ाइल 1 और फ़ाइल 2 में हमेशा मेरे परिदृश्य में समान मात्रा में लाइनें होंगी, जो कि चीजों को आसान बनाती हैं।

जवाबों:


34

इस नौकरी के लिए सही उपकरण शायद है paste

paste -d '' file1 file2

man pasteविवरण के लिए देखें।


आप prकमांड का उपयोग भी कर सकते हैं :

pr -TmJS"" file1 file2

कहा पे

  • -T बंद हो जाता है
  • -mJ एम erge files, J oining full lines
  • -S"" खाली स्ट्रिंग वाले कॉलम को अलग करें

यदि आप वास्तव में इसे शुद्ध बैश शेल (अनुशंसित नहीं) का उपयोग करके करना चाहते थे, तो यही मैं सुझाव देता हूं:

while IFS= read -u3 -r a && IFS= read -u4 -r b; do 
  printf '%s%s\n' "$a" "$b"
done 3<file1 4<file2

(केवल इस सहित क्योंकि विषय एक और प्रस्तावित शुद्ध-बास समाधान के लिए टिप्पणियों में आया था।)


1
बहुत सरल समाधान के लिए धन्यवाद। जब पेस्ट का उपयोग करने की बात आती है तो क्या मुझे कभी पोर्टेबिलिटी की चिंता करनी चाहिए?
TuxForLife

1
@ user264974 पेस्ट GNU Coreutils में है इसलिए आप संभवतः काफी सुरक्षित हैं।
nettux

8

के माध्यम से रास्ता:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2"फ़ाइल 2 से पूरी पंक्ति पढ़ता है और x चर में रखता है ।
  • print $0xसे पूरे लाइन प्रिंट file1 का उपयोग करके $0तो xजिनमें से बचाया लाइन है करें 2

बहुत अच्छा है एक जाग विकल्प है, मैं इसके बजाय इसका इस्तेमाल कर सकता हूं!
TuxForLife

4

pasteजाने का रास्ता है । यदि आप कुछ अन्य तरीकों की जाँच करना चाहते हैं, तो यहाँ एक pythonसमाधान है:

#!/usr/bin/env python2
import itertools
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    lines = itertools.izip_longest(f1, f2)
    for a, b in lines:
        if a and b:
            print a.rstrip() + b.rstrip()
        else:
            if a:
                print a.rstrip()
            else:
                print b.rstrip()

यदि आपके पास कुछ पंक्तियाँ हैं:

#!/usr/bin/env python2
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    print '\n'.join((a.rstrip() + b.rstrip() for a, b in zip(f1, f2)))

ध्यान दें कि असमान संख्या की रेखाओं के लिए, यह उस फ़ाइल की अंतिम पंक्ति पर समाप्त हो जाएगा जो पहले समाप्त होती है।


3

इसके अलावा, शुद्ध के साथ bash(ध्यान दें कि यह पूरी तरह से खाली लाइनों की उपेक्षा करेगा):

#!/bin/bash

IFS=$'\n' GLOBIGNORE='*'
f1=($(< file1))
f2=($(< file2))
i=0
while [ "${f1[${i}]}" ] && [ "${f2[${i}]}" ]
do
    echo "${f1[${i}]}${f2[${i}]}" >> out
    ((i++))
done
while [ "${f1[${i}]}" ]
do
    echo "${f1[${i}]}" >> out
    ((i++))
done
while [ "${f2[${i}]}" ]
do
    echo "${f2[${i}]}" >> out
    ((i++))
done

यह सीधे तौर पर गलत है। यह बिल्कुल काम नहीं करता है। या तो mapfileफ़ाइलों को सरणियों में पढ़ने के लिए उपयोग करें, या दो readकमांडों के साथ थोड़ी देर के लूप का उपयोग करें , प्रत्येक उनके fd से पढ़ना।
जिरह

@geirha तुम सही हो, मैंने वाक्य रचना के साथ खिलवाड़ किया, यह अब ठीक है।
कोस

काफी नहीं। अपडेट किए गए कोड के साथ, खाली लाइनों को नजरअंदाज कर दिया जाएगा, और यदि किसी भी लाइन में ग्लोब वर्ण हैं, तो लाइन को मेल फ़ाइल नाम से बदला जा सकता है। तो कभी भी उपयोग array=( $(cmd) )या array=( $var )mapfileइसके बजाय उपयोग करें ।
जिरह

@geirha आप निश्चित रूप से सही हैं, मैंने ग्लोब पात्रों का ध्यान रखा, लेकिन मैंने नई रेखा को नजरअंदाज कर दिया, क्योंकि ऐसा करने के लिए और इसमें से एक अच्छा समाधान बनाने के लिए इसे फिर से लिखने की आवश्यकता है। मैंने इसे निर्दिष्ट किया है और इस संस्करण को उस समय छोड़ देगा जब यह इस बीच किसी के लिए उपयोगी होगा। आपके अंक के लिए अब तक धन्यवाद।
कोस

2

पर्ल रास्ता, समझने में आसान:

#!/usr/bin/perl
$filename1=$ARGV[0];
$filename2=$ARGV[1];

open(my $fh1, "<", $filename1) or die "cannot open < $filename1: $!";
open(my $fh2, "<", $filename2) or die "cannot open < $filename2: $!";

my @array1;
my @array2;

while (my $line = <$fh1>) {
  chomp $line;
  push @array1, $line;
}
while (my $line = <$fh2>) {
  chomp $line;
  push @array2, $line;
}

for my $i (0 .. $#array1) {
  print @array1[$i].@array2[$i]."\n";
}

के साथ शुरू:

./merge file1 file2

आउटपुट:

foobar
icecream
twohundred
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.