Junte sete arquivos com awk linha por linha

Junte sete arquivos com awk linha por linha

Tenho sete (ou oito e assim por diante) arquivos com o mesmo número de linhas.

arquivo1

1.001
1.002
1.003
1.004

arquivo2

2.001
2.002
2.003
2.004

arquivo3

3.001
3.002
3.003
3.004

etc.

Saída desejada:

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

Como fazer isso com um script curto no awk?

Responder1

Como disse o steeldriver, a maneira razoável de fazer isso é com 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

Mas, se você precisar usar 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

O script awk mantém todos os dados na memória. Se os arquivos forem grandes, isso pode ser um problema. Mas, para esta tarefa, pasteé melhor e mais simples de qualquer maneira.

Como funciona

Neste script ahá um array que a[i]é a saída para line i. À medida que lemos cada um dos arquivos subsequentes, acrescentamos as novas informações de line iao final de a[i]. Após terminarmos de ler os arquivos, imprimimos os valores em formato a. Em mais detalhes:

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

    FNRé o número da linha do arquivo atual que estamos lendo e $0é o conteúdo dessa linha. Este código é adicionado $0ao final de a[FNR]. Exceto se ainda estivermos lendo o primeiro arquivo, colocamos ponto e vírgula antes de $0. Isso é feito usando a instrução ternária de aparência complexa: (FNR==NR?"":";"). Este é realmente apenas um comando if-then-else. Se estivermos lendo o primeiro arquivo, ou seja, if FNR==NR, ele retornará uma string vazia "". Caso contrário, ele retorna um ponto e vírgula, ;.

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

    Depois de terminarmos de ler todos os arquivos, isso imprime os dados que acumulamos no array a.

Responder2

POSIX estranho; isso funciona com uma quantidade arbitrária de arquivos, e os arquivos nem precisam ter a mesma quantidade de linhas. O script continua até que todos os arquivos fiquem sem linhas:

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

informação relacionada