unir varias líneas basadas en la columna1

8

Tengo un archivo como el de abajo ...

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

Quiero convertirlo (unirlo) 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
fuente
2
¿Realmente tiene las líneas en blanco adicionales en su archivo de entrada? De lo contrario, edítelos y elimínelos, debe mostrar el archivo exactamente como está.
terdon

Respuestas:

10

Si no le importa el orden de salida:

$ 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

Explicación

  • NF>1 lo que significa que solo necesitamos procesar la línea que no está en blanco.
  • Guardamos todo el primer campo en la matriz asociativa a, con la clave es el primer campo, el valor es el segundo campo (o el resto de la línea). Si la clave ya tiene valor hasd, concatenamos dos valores.
  • En ENDbloque, recorremos la matriz asociativa a, imprimimos todas sus claves con el valor correspondiente.

O usando perlmantendrá el orden:

$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
fuente
su solución perl de mi pregunta unix.stackexchange.com/questions/124181/… también debería funcionar ¿verdad?
Ramesh
No. El OP quiere concatenar una cadena basada en la columna 1, independientemente de si está duplicada o no. Tu pregunta no quiere duplicarse.
Cuonglm
oh ok A primera vista, parecía casi similar a mi pregunta. :)
Ramesh
1
Aseado, +1! Sin embargo, eso no mantiene el orden, solo lo recrea en este ejemplo particular donde los campos están en orden alfabético.
terdon
Solo para reír, había escrito casi exactamente el mismo enfoque antes de leer tu respuesta: perl -F, -lane 'next unless /./;push @{$k{$F[0]}}, ",@F[1..$#F]"; END{print "$_@{$k{$_}}" foreach keys(%k)}' file:) ¡Grandes mentes piensan igual!
terdon
1

Oh, esa es fácil. Aquí hay una versión simple que mantiene el orden de las teclas tal como aparecen en el archivo:

$ 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 salida debería verse así:

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 no le importa tener una línea en blanco adicional al final, simplemente reemplace la printflínea conprintf("%s %s\n\n", Key[j], Val[Key[j]]);


fuente