joindre plusieurs lignes sur la base de column1

8

J'ai un fichier comme ci-dessous ..

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

Je veux le convertir (joindre) en:

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
la source
2
Avez-vous réellement des lignes vierges supplémentaires dans votre fichier d'entrée? Sinon, veuillez les modifier et les supprimer, vous devez afficher le fichier exactement tel qu'il est.
terdon

Réponses:

10

Si cela ne vous dérange pas l'ordre de sortie:

$ 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

Explication

  • NF>1 ce qui signifie que nous devons uniquement traiter la ligne qui n'est pas vide.
  • Nous enregistrons tout le premier champ dans le tableau associatif a, avec la clé est le premier champ, la valeur est le deuxième champ (ou le reste de la ligne). Si la clé a déjà une valeur, nous concatérons deux valeurs.
  • En ENDbloc, nous parcourons le tableau associatif a, imprimons toutes ses clés avec la valeur correspondante.

Ou en utilisant perl, la commande sera conservée:

$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
la source
votre solution perl de ma question unix.stackexchange.com/questions/124181/… devrait également fonctionner correctement?
Ramesh
Non. L'OP souhaite concaténer une chaîne basée sur la colonne 1, qu'elle soit dupliquée ou non. Votre question ne veut pas être dupliquée.
cuonglm
Ah d'accord. À première vue, cela ressemblait presque à ma question. :)
Ramesh
1
Neat, +1! Cependant, cela ne conserve pas l'ordre, il le recrée uniquement dans cet exemple particulier où les champs sont classés par ordre alphabétique.
terdon
Juste pour rire, j'avais écrit presque exactement la même approche avant de lire votre réponse: perl -F, -lane 'next unless /./;push @{$k{$F[0]}}, ",@F[1..$#F]"; END{print "$_@{$k{$_}}" foreach keys(%k)}' file:) Les grands esprits se ressemblent!
terdon
1

Oh, c'est facile. Voici une version simple qui conserve l'ordre des clés telles qu'elles apparaissent dans le fichier:

$ 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

La sortie devrait ressembler à ceci:

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

Si cela ne vous dérange pas d'avoir une ligne vierge supplémentaire à la fin, remplacez simplement la printfligne parprintf("%s %s\n\n", Key[j], Val[Key[j]]);


la source