Ich habe eine CSV-Eingabedatei, die folgendermaßen aussieht:
john,Hello my name
john,is John
katie,Whereas my
katie,name is Katie
bob,And I am Bob.
Die Datei ist so sortiert, dass die Namen (in der ersten Spalte) zusammenhängend und der Text (zweite Spalte) logisch sortiert ist.
Gibt es eine standardisierte Möglichkeit, die erste Spalte zu „gruppieren“ (unter Verwendung der SQL-Terminologie) und die zweite Spalte zu verketten?
Meine gewünschte Ausgabe ist:
john,Hello my name is John
katie,Whereas my name is Katie
bob,And I am Bob.
Antwort1
Durch umfassende Kenntnis der Länge jedes Blocks bleiben uns die kleinen Komplikationen erspart, die mit der Behandlung einer Randbedingung verbunden sind, für die andernfalls ein END-Block mit replizierter Funktionalität erforderlich wäre.
Ich befürworte diesen Ansatz nicht zugunsten der akzeptierten Antwort von Gilles. Ich stelle ihn lediglich vor, um einen alternativen Ansatz zu demonstrieren, der bei der Behandlung komplizierter Probleme (dieses ist keins davon) zu einer erheblichen Reduzierung der Komplexität führen könnte (auf Kosten von E/A und möglicherweise Speicher).
a
ist ein namenindiziertes Array von Blocklängen. n
ist die Anzahl der verbleibenden Zeilen in einem Block:
awk -F, '
FNR==NR {a[$1]++; next}
n {print " "$2}
!n {print; n=a[$1]}
!--n {print "\n"}
' ORS= data data
Antwort2
Dafür gibt es kein Standardtool, nein. Diese Aufgabe ist ziemlich gut für awk geeignet: Zeilen nacheinander lesen, das erste Feld speichern und das zweite Feld akkumulieren und das Ergebnis ausdrucken, wenn sich das erste Feld ändert. Die Hauptschwierigkeit (die kleinere Schwierigkeit) besteht darin, dass das Ergebnis auch ausgedruckt werden muss, wenn die letzte Zeile erreicht ist.
awk -F, '
1 {current = $1; sub(/^[^,]*,/,"")}
current == previous {acc = acc " " $0; next}
NR != 1 {print previous "," acc}
1 {previous = current; acc = $0}
END {if (NR) print previous "," acc}'
Antwort3
awk -F, '{a[$1]=a[$1]? a[$1]" "$2 : $2;}END{for (i in a)print i, a[i];}' OFS=, filename