Dosyaları satır satır bazında nasıl birleştirebilirim?


22

kedi dosyası1

foo
ice
two

kedi dosyası2

bar
cream
hundred

Istenilen çıktı:

foobar
icecream
twohundred

Dosya1 ve dosya2, işleri kolaylaştırır diye her zaman senaryomda aynı miktarda satıra sahip olacaktır.

Yanıtlar:


34

Bu iş için doğru araç muhtemelen paste

paste -d '' file1 file2

Detaylar man pasteiçin bakınız.


prKomutu da kullanabilirsiniz :

pr -TmJS"" file1 file2

nerede

  • -T sayfalamayı kapatır
  • -mJ m erge dosyaları, J tam satırları oining
  • -S"" sütunları boş bir dize ile ayır

Eğer varsa gerçekten saf bash kabuğunu (önerilmez) kullanarak yapmak istedim, o zaman bu ben öneririm budur:

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

(Sadece bu konu dahil, çünkü konu başka önerilen saf bash çözümüne yorumlarda bulundu.)


1
Müthiş, çok basit bir çözüm için teşekkür ederim. Yapıştırma kullanımı konusunda taşınabilirlik konusunda hiç endişelenmeli miyim?
TuxForLife

1
@ user264974 macunu GNU Coreutils içinde, bu yüzden muhtemelen oldukça güvendesiniz.
nettux

8

aracılığıyla şekilde:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2" satırın tamamını okur file2'deki x değişkeninde tutar .
  • print $0xden bütün çizgi yazdırır Dosya1 kullanılarak $0daha sonra xkaydedilmiş hattı olan dosya2'nin .

Bir awk alternatifi olması çok iyi, bunun yerine bunu kullanabilirim!
TuxForLife

4

pastegitmenin yolu bu . Diğer bazı yöntemleri kontrol etmek istiyorsanız, işte size bir pythonçözüm:

#!/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()

Çok az sayıda hattınız varsa:

#!/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)))

Eşit olmayan satır sayısı için bunun ilk önce biten dosyanın son satırında biteceğini unutmayın.


3

Ayrıca, saf bash(bunun tamamen boş satırları yoksaymayacağına dikkat edin):

#!/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

Bu sadece düz yanlış. Hiç çalışmıyor. Ya kullanım mapfilediziler içine dosyalarını okumak, ya da iki sahip bir süre döngü kullanmak readher biri kendi fd okuma, komutları.
geirha

@geirha Haklısın, ben sözdizimi ile karışıklık, şimdi tamam.
kos,

tam değil. Güncellenen kodda boş satırlar yoksayılır ve herhangi bir satır glob karakterleri içeriyorsa, satır eşleşen dosya adları ile değiştirilebilir. Yani asla array=( $(cmd) )ya da kullanmayın array=( $var ). Yerine mapfilekullanın.
geirha

@geirha Elbette haklısın, dünya karakterlerine baktım ama yeni satırı görmezden geldim, çünkü bunu yapmak için ve iyi bir çözüm yapabilmek için yeniden yazılması gerekiyor. Bunu belirttim ve bu süre içinde birisinin yararı olabilir diye bu sürümü bırakacağım. Şimdiye kadar puanlarınız için teşekkürler.
kos,

2

Perl yolu, anlaşılması kolay:

#!/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";
}

İle başla:

./merge file1 file2

Çıktı:

foobar
icecream
twohundred
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.