Une sete arquivos com o awk linha por linha

2

Eu 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?

    
por akj 19.06.2016 / 21:40

2 respostas

6

Como a steeldriver disse, 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 essa tarefa, paste é melhor e mais simples de qualquer maneira.

Como funciona

Neste script a é uma matriz com a[i] sendo a saída da linha i . À medida que lemos cada um dos arquivos subsequentes, anexamos as novas informações da linha i ao final de a[i] . Depois de terminarmos de ler os arquivos, imprimimos os valores em a . Mais detalhadamente:

  • 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 adiciona $0 ao final de a[FNR] . Exceto se ainda estivermos lendo o primeiro arquivo, colocamos um ponto-e-vírgula antes de $0 . Isso é feito usando a declaração ternária complexa: (FNR==NR?"":";") . Este é realmente apenas um comando if-then-else. Se estivermos lendo o primeiro arquivo, ou seja, se FNR==NR , ele retornará uma string vazia "" . Caso contrário, 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 .

por 19.06.2016 / 22:26
0

POSIX Awk; isso funciona com uma quantidade arbitrária de arquivos, e os arquivos não até tem que ter a mesma quantidade de linhas. O roteiro continua até que todos os arquivos estão fora de linha:

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

Tags