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 a
há 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 i
ao 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$0
ao final dea[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, ifFNR==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)
}