行ごとにファイルをマージするにはどうすればよいですか?


22

猫のファイル1

foo
ice
two

猫のファイル2

bar
cream
hundred

望ましい出力:

foobar
icecream
twohundred

私のシナリオでは、file1とfile2の行数は常に同じになります。

回答:


34

この仕事に最適なツールはおそらく paste

paste -d '' file1 file2

詳細man pasteを参照してください。


pr次のコマンドも使用できます。

pr -TmJS"" file1 file2

どこで

  • -T ページネーションをオフにします
  • -mJ m個の ERGEファイル、J oiningフルライン
  • -S"" 列を空の文字列で区切ります

純粋なbashシェル(推奨されません)を使用してそれを本当に実行したい場合、これは私が提案するものです:

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

(これは、主題が別の提案された純粋なbashソリューションへのコメントで出てきたためにのみ含まれています。)


1
素晴らしい、非常にシンプルなソリューションをありがとう。ペーストの使用に関して、移植性について心配する必要はありますか?
TuxForLife

1
@ user264974 pasteはGNU Coreutilsに含まれているため、おそらくかなり安全です。
nettux

8

道:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2"file2から行全体を読み取り、x変数に保持します。
  • print $0xfile2の保存行であるthen を使用して、file1から行全体を出力します。$0x

awkの代替案があるのは非常に良いので、代わりにこれを使用するかもしれません!
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から読み込む2つのコマンドでwhileループを使用します。
ガイラ

@geirhaあなたは正しい、私は構文を台無しにした、今は大丈夫です。
コス

そうではありません。更新されたコードでは、空の行は無視され、行にグロブ文字が含まれている場合、その行は一致するファイル名に置き換えられる可能性があります。array=( $(cmd) )またはを使用しないでくださいarray=( $var )mapfile代わりに使用してください。
ガイラ

@geirhaもちろん、グロブ文字の世話をしましたが、改行を無視したままにしておきました。これを指定し、その間に誰かに役立つように、このバージョンを残します。これまでのところあなたのポイントをありがとう。
コス

2

わかりやすいperlの方法:

#!/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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.