awk で 7 つのファイルを行ごとに結合する

awk で 7 つのファイルを行ごとに結合する

同じ行数のファイルが 7 つ (または 8 つなど) あります。

ファイル1

1.001
1.002
1.003
1.004

ファイル2

2.001
2.002
2.003
2.004

ファイル3

3.001
3.002
3.003
3.004

望ましい出力:

1.001;2.001;3.001;4.001;5.001;6.001;7.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004

awk の短いスクリプトでそれを実行するにはどうすればよいでしょうか?

答え1

steeldriver が言ったように、これを行う合理的な方法は次のとおりですpaste

$ paste -d';' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004

ただし、次のものを使用する必要がある場合awk:

$ awk '{a[FNR]=a[FNR](FNR==NR?"":";")$0} END{for (i=1;i<=FNR;i++) print a[i]}' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004

awk スクリプトはすべてのデータをメモリ内に保持します。ファイルが大きい場合、これが問題になる可能性があります。しかし、このタスクでは、pasteとにかくこれがより優れていて簡単です。

使い方

このスクリプトには、行 の出力aである配列があります。後続の各ファイルを読み取る際に、行 の新しい情報を の末尾に追加します。ファイルの読み取りが完了したら、 の値を出力します。詳細:a[i]iia[i]a

  • a[FNR]=a[FNR](FNR==NR?"":";")$0

    FNRは、現在読み取っているファイルの行番号で、$0はその行の内容です。このコードは$0の末尾に追加されますa[FNR]。ただし、まだ最初のファイルを読み取っている場合は、 の前にセミコロンを入れます$0。これは、複雑に見える三項ステートメントを使用して行われます。(FNR==NR?"":";")これは、実際には単なる if-then-else コマンドです。最初のファイルを読み取っている場合、つまり の場合FNR==NRは、空の文字列 を返します""。そうでない場合は、セミコロン を返します;

  • END{for (i=1;i<=FNR;i++) print a[i]}

    すべてのファイルの読み取りが完了すると、配列に蓄積されたデータが出力されますa

答え2

POSIX Awk。これは任意の数のファイルで動作し、ファイルの行数が同じである必要もありません。スクリプトは、すべてのファイルの行数がなくなるまで続行されます。

BEGIN {
  do {
    br = ch = 0
    while (++ch < ARGC)
      if (getline < ARGV[ch]) {
        printf ch < ARGC - 1 ? $0 ";" : $0 RS
        br = 1
      }
  } while (br)
}

関連情報