
Ainda estou aprendendo programação e tentei muitas coisas, mas não consigo obter o formato correto. eu tenho umdelimitado por tabulaçãoarquivo com 17 colunas e muitas (cerca de 50.000) linhas. O arquivo já está classificado pela primeira coluna. Quero mesclar linhas que possuem a mesma primeira coluna (A), mas todas as outras 16 colunas são diferentes e quero manter todas as informações em uma linha, de preferência na mesma coluna componto e vírgula;como um delimitador entre eles. Quero manter a tabulação como delimitador no arquivo de saída. Muito obrigado pelas respostas e se você também pudesse explicar onde errei seria ainda melhor :).
Eu tentei até agora:
awk -F'\t' 'NF>1{a[$1] = a[$1]";"$2}END{for(i in a){print i""a[i]}}' filename.txt
perl -F',' -anle 'next if /^$/;$h{$F[0]} = $h{$F[0]}.", ".$F[1];
END{print $_,$h{$_},"\n" for sort keys %h}' filename.txt
FORMATO DE ARQUIVO (outras 15 colunas têm o mesmo formato da coluna B)
A B C
123 fvv ggg
123 kjf ggg
123 ccd att
567 abc gst
567 abc hgt
879 ttt tyt
A saída que desejo (preciso de todas as 17 colunas e para as colunas 2 a 16 preciso da mesma saída das colunas B e C). Todos os casos de B devem estar abaixo de B e todos os casos de C devem estar abaixo de C e todos os casos de D devem estar abaixo de D etc. Portanto, a saída tem 17 colunas assim como a entrada e em vez de 50.000 linhas, agora deve ter cerca de 20.000 , porque há muitas repetições para a coluna 1 (para este arquivo específico):
A B C
123 fvv;kjf;ccd ggg;ggg;att
567 abc;abc gst;hgt
879 ttt lll
Responder1
awk '{
if(NR!=1){a[$1]=$2";"a[$1]}
else print $0}
END{
n = asorti(a, b);
for (n in b) {
print b[n],a[b[n]]
}
}'
Responder2
Uma solução Perl:
$ perl -F"\t" -anle 'if($.==1){print; next} push @{$k{$F[0]}},@F[1..$#F];
END{print "$_\t" . join(";",@{$k{$_}}) for sort keys(%k)}' file
A B
123 fvv;kjf;ccd
567 abc;abc
879 ttt
Isso pode funcionar em um número arbitrário de campos. No entanto, é necessário carregar algumas coisas na memória e isso pode ser um problema se o arquivo for grande.
Quanto a onde você errou, não podemos dizer a menos que você explique o que realmente aconteceu, mas, pensando bem, sua tentativa de Perl falharia porque:
- Você está usando
-F,
o qual define o separador de campos como uma vírgula quando sua entrada possui tabulações. - Você está usando
-l
eprint "foo\n"
. O-l
já adiciona uma nova linha a cada chamada de impressão, então você terá várias linhas em branco. - Você está usando
$h{$F[0]}.", ".$F[1];
para anexar, então na primeira vez que for executado e$h{$F[0]}
não estiver definido, você adicionará um extra,
no início do seu valor armazenado. - Você está olhando apenas para o segundo campo, ignorando todos os outros.
Da mesma forma, você awk
falhará porque:
- Você está imprimindo
foo""bar
o que concatenará a saída sem espaço entre cada campo. Você desejaprint foo,bar
e também desejaOFS="\t"
uma saída separada por tabulações. - Você está olhando apenas para o segundo campo, ignorando todos os outros.
Responder3
desculpas por esta frase, mas aqui vai -
awk 'BEGIN{FS="\t"} {for(i=2; i<=NF; i++) { if (!a[$1]) a[$1]=$1FS$i ;else a[$1]=a[$1]";"$i};if ($1 != old) b[j++] = a[old];old=$1 } END{for (i=0; i<j; i++) print b[i] }' 1
123 fvv ;kjf;ccd
567 abc;abc
879 ttt
Responder4
awk '
function p(n,A){
s = n
for(i=2;i<=NF;i++){
s = s "\t" A[i]
A[i] = $i
}
if(n)
print s
}
NR==1{
print
next
}
$1==n{
for(i=2;i<=NR;i++)
A[i] = A[i] ";" $i
next
}
{
p(n,A)
n = $1
}
END{
p(n,A)
}
' file