unir várias linhas com base na coluna1

8

Eu tenho um arquivo como abaixo ..

abc, 12345
def, text and nos    
ghi, something else   
jkl, words and numbers

abc, 56345   
def, text and nos   
ghi, something else 
jkl, words and numbers

abc, 15475  
def, text and nos 
ghi, something else
jkl, words and numbers

abc, 123345
def, text and nos
ghi, something else  
jkl, words and numbers

Eu quero convertê-lo como:

abc, 12345, 56345, 15475, 123345
def, text and nos, text and nos,text and nos,text and nos
ghi, something else, something else, something else, something else   
jkl, words and numbers, words and numbers, words and numbers, words and numbers
pvkbhat
fonte
2
Você realmente tem as linhas em branco extras no seu arquivo de entrada? Caso contrário, edite e remova-os. Você deve mostrar o arquivo exatamente como ele é.
terdon

Respostas:

10

Se você não se importa com a ordem de saída:

$ awk -F',' 'NF>1{a[$1] = a[$1]","$2};END{for(i in a)print i""a[i]}' file 
jkl, words and numbers, words and numbers, words and numbers, words and numbers
abc, 12345, 56345, 15475, 123345
ghi, something else, something else, something else, something else
def, text and nos, text and nos, text and nos, text and nos

Explicação

  • NF>1 ou seja, precisamos processar apenas a linha que não está em branco.
  • Nós salvamos todo o primeiro campo na matriz associativa a, com a chave é o primeiro campo, o valor é o segundo campo (ou o restante da linha). Se a chave já possui valor, concatizamos dois valores.
  • No ENDbloco, percorremos o array associativo a, imprimimos todas as suas chaves com o valor correspondente.

Ou usar perlmanterá a ordem:

$perl -F',' -anle 'next if /^$/;$h{$F[0]} = $h{$F[0]}.", ".$F[1];
    END{print $_,$h{$_},"\n" for sort keys %h}' file
abc, 12345, 56345, 15475, 123345

def, text and nos, text and nos, text and nos, text and nos

ghi, something else, something else, something else, something else

jkl, words and numbers, words and numbers, words and numbers, words and numbers
cuonglm
fonte
sua solução perl da minha pergunta unix.stackexchange.com/questions/124181/… também deve funcionar, certo?
Ramesh
Não. O OP deseja concatear a string com base na coluna 1, independentemente de duplicada ou não. Sua pergunta não deseja duplicar.
amigos estão dizendo sobre cuonglm
Ah ok. À primeira vista, parecia quase semelhante à minha pergunta. :)
Ramesh
1
Limpo, +1! Porém, isso não mantém a ordem, apenas a recria neste exemplo específico em que os campos estão em ordem alfabética.
terdon
Apenas para rir, eu escrevi quase exatamente a mesma abordagem antes de ler sua resposta: perl -F, -lane 'next unless /./;push @{$k{$F[0]}}, ",@F[1..$#F]"; END{print "$_@{$k{$_}}" foreach keys(%k)}' file:) Grandes mentes pensam da mesma forma!
terdon
1

Oh, isso é fácil. Aqui está uma versão simples que mantém a ordem das chaves conforme elas aparecem no arquivo:

$ awk -F, '
    /.+/{
        if (!($1 in Val)) { Key[++i] = $1; }
        Val[$1] = Val[$1] "," $2; 
    }
    END{
        for (j = 1; j <= i; j++) {
            printf("%s %s\n%s", Key[j], Val[Key[j]], (j == i) ? "" : "\n");       
        }                                    
    }' file.txt

A saída deve ficar assim:

abc, 12345, 56345, 15475, 123345

def, text and nos, text and nos, text and nos, text and nos

ghi, something else, something else, something else, something else

jkl, words and numbers, words and numbers, words and numbers, words and numbers

Se você não se importa em ter uma linha em branco extra no final, substitua a printflinha porprintf("%s %s\n\n", Key[j], Val[Key[j]]);


fonte