ファイルを1行ずつマージ

ファイルを1行ずつマージ

10個のファイルがあり、各ファイルの最初の行、各ファイルの2番目の行などを1つの大きなファイルにコピーしたいと思います。

ファイル1.txtは

A 
B 
C 
D 

ファイル2.txtは

E 
F
G
H

file3.txtは

I 
J
K
L

ありますように

A 
E
I
B
F
J
C
G
K
....

ありがとう

答え1

これを使用できますpaste。区切り文字を改行に設定します。

$ paste -d'\n' file1 file2 file3
A 
E 
I 
B 
F
J
C 
G
K
D 
H
L

答え2

代替方法は次のとおりです(ANSI-C引用符をサポートするpasteシェルGNU prでテストされています)。

pr -mts$'\n' <files>

1つの利点は、この-sオプションが複数文字の区切り文字にも機能することです。


タグが付けられているので、コマンドを使用sedできます(で利用可能ですが、他の実装についてはわかりません)。RGNU sed

sed -e 'R f2' -e 'R f3' f1

答え3

#!/usr/bin/perl

use strict;

# how many files to open? 10 in the question, 3 in examples.
my $numfh=3;

# a counter for the number of open file handles
my $openfh=$numfh;

# open an array of filehandles, one for each input file.
my @fh = ();
for my $i (1..$numfh) {
  open($fh[$i],"<","file$i.txt") || die "Couldn't open file$i.txt for read: $!";
};

# open the output file.
open (my $out,">","bigfile.txt") || die "Couldn't open bigfile.txt for write: $!";

# repeat until there are no more open file handles.
until ($openfh < 1) {
  for my $i (1..$numfh) {
    if (eof($fh[$i])) {
      # if an input file is eof, close it and decrement openfh counter.
      $openfh--;
      close($fh[$i]);
    } else {
      # print a line of input from the current input file to the output file.
      print $out scalar readline $fh[$i]
    };
  };
}

たとえば、別の名前で保存しmerge.plて実行可能にしますchmod +x merge.pl。次に、次のように実行します。

$ ./merge.pl

出力:

$ cat bigfile.txt 
A
E
I
B
F
J
C
G
K
D
H
L

@ARGVを使用して@terdonのSTDOUTとして印刷するバージョンは次のとおりです。

#!/usr/bin/perl

use strict;

my @fh = ();
my $i=1;

for my $f (@ARGV) {
  open($fh[$i++], "<", $f) || die "Couldn't open $f for read: $!";
};

my $numfh=$#fh; my $openfh=$numfh;

until ($openfh < 1) {
  for my $i (1..$numfh) {
    if (eof($fh[$i])) {
      $openfh--;
      close($fh[$i]);
    } else {
      print scalar readline $fh[$i]
    };
  };
}

または、ハッシュを使用して配列の代わりにファイルハンドルを保存します。

#!/usr/bin/perl

use strict;

my %fh = ();

for (@ARGV) {
  open($fh{$_}, "<", $_) || die "Couldn't open $_ for read: $!";
};

while (keys %fh) {
  for my $f (@ARGV) {
    next unless (defined($fh{$f}));
    if (eof($fh{$f})) {
      close($fh{$f});
      delete($fh{$f});
    } else {
      print scalar readline $fh{$f}
    };
  };
}

次のように実行します。

$ ./merge.pl file[123].txt > bigfile.txt

出力はハードコードされたバージョンと同じです。

答え4

使用GNU sedreadコマンドを使用して、R入力ファイルから上位数行を段階的に抽出して、マージされた出力を取得できます。

sed -e "
  $(printf 'R%s\n' file{2..9}.txt file10.txt)
" file1.txt

perl -lne '
  push @{$A[@ARGV]}, $_}{
  for my $i (0..$#{$A[0]}){
    print for map { $A[$_][$i] } reverse 0..$#A
  }
' file{1..9}.txt file10.txt

ここでは、2D array@Aとも呼ばれるAoAにファイルを保存します。最初のインデックスは位置パラメータリストのファイルの場所を表し、2番目のインデックスはその特定のファイルのデータを表します。終了ブロックでは、}{各配列から1つの要素を選択して配列を圧縮します。

関連情報