Verbinden Sie mehrere Zeilen basierend auf Spalte1

8

Ich habe eine Datei wie unten ..

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

Ich möchte es konvertieren (beitreten) als:

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
quelle
2
Haben Sie tatsächlich die zusätzlichen Leerzeilen in Ihrer Eingabedatei? Wenn nicht, bearbeiten und entfernen Sie sie. Sie sollten die Datei genau so anzeigen , wie sie ist.
Terdon

Antworten:

10

Wenn Ihnen die Reihenfolge der Ausgabe nichts ausmacht:

$ 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

Erläuterung

  • NF>1 Das heißt, wir müssen nur eine Zeile verarbeiten, die nicht leer ist.
  • Wir speichern alle ersten Felder im assoziativen Array a, wobei der Schlüssel das erste Feld ist, der Wert das zweite Feld (oder der Rest der Zeile). Wenn der Schlüssel bereits einen Wert hat, konzentrieren wir uns auf zwei Werte.
  • Im ENDBlock durchlaufen wir das assoziative Array aund drucken alle seine Schlüssel mit dem entsprechenden Wert.

Oder mit perlwird die Reihenfolge beibehalten:

$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
quelle
Ihre Perl-Lösung aus meiner Frage unix.stackexchange.com/questions/124181/… sollte auch richtig funktionieren?
Ramesh
Nein. Das OP möchte eine Zeichenfolge basierend auf Spalte 1 zusammenfassen, unabhängig davon, ob sie dupliziert wurde oder nicht. Ihre Frage möchte nicht dupliziert werden.
Cuonglm
Oh ok. Auf den ersten Blick schien es meiner Frage fast ähnlich zu sein. :)
Ramesh
1
Ordentlich, +1! Das bedeutet nicht , hält die Reihenfolge aber, es erschafft es nur in diesem speziellen Beispiel , wo die Felder in alphabetischer Reihenfolge sind.
Terdon
Nur zum Lachen hatte ich fast genau den gleichen Ansatz geschrieben, bevor ich Ihre Antwort gelesen habe: perl -F, -lane 'next unless /./;push @{$k{$F[0]}}, ",@F[1..$#F]"; END{print "$_@{$k{$_}}" foreach keys(%k)}' file:) Großartige Köpfe denken gleich!
Terdon
1

Oh, das ist einfach. Hier ist eine einfache Version, die die Reihenfolge der Schlüssel in der Datei beibehält:

$ 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

Die Ausgabe sollte folgendermaßen aussehen:

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

Wenn es Ihnen nichts ausmacht, am Ende eine zusätzliche Leerzeile zu haben, ersetzen Sie die printfZeile einfach durchprintf("%s %s\n\n", Key[j], Val[Key[j]]);


quelle