Zum Beispiel habe ich eine Datei:Wie man mehrere Zeichenfolgen mit einem Schlüssel zusammenfasst?
key1 1212
key2 1212
key1 32332
key2 3232
key2 3232
Ich möchte Datei erhalten:
key1 1212,32332
key2 1212,3232,3232
Zum Beispiel habe ich eine Datei:Wie man mehrere Zeichenfolgen mit einem Schlüssel zusammenfasst?
key1 1212
key2 1212
key1 32332
key2 3232
key2 3232
Ich möchte Datei erhalten:
key1 1212,32332
key2 1212,3232,3232
In awk:
$ awk '{a[$1]=a[$1](a[$1]==""?"":",")$2}END{for(i in a)print i,a[i]}' file
key1 1212,32332
key2 1212,3232,3232
Erklärt:
awk '{ # use awk for this kind of stuff
a[$1]=a[$1] (a[$1]=="" ? "" : ",") $2 # hash on first col and append seconds
}
END { # after everything is hashed
for(i in a) # for each entry in hash a
print i,a[i] # output key and data
}' file # oh yeah the file
Edit: Anstatt awk tun die Pufferung (dh. Hashing zu a
) könnten wir sort
verwenden, um die Datei zu sortieren und dann den Schlüssel und alle Daten danach kommasepariert auszugeben. awk für den letzten Teil wieder verwendet:
$ sort file | awk '$1!=p{printf "%s%s",(NR>1?ORS:""),$1}{printf "%s%s", ($1==p?",":OFS),$2;p=$1}END{print ""}'
key1 1212,32332
key2 1212,3232,3232
Hier sort
ist keine Phantasie Parameter nicht gegeben, aber in der realen Welt benötigt werden, um einige könnten. Die awk Teil erklärt:
sort file | \ # sort the file
awk ' # before feeding to awk
$1!=p { # if key is different from previous key
printf "%s%s",(NR>1?ORS:""),$1 # newline and print the key
}
{
printf "%s%s", ($1==p?",":OFS),$2 # print the data comma-separated
p=$1 # store key for comparing on the next round
}
END{
print "" # finish the last line nicely
}'
antwort höchstwahrscheinlich ist gut und funktioniert, aber ich versuche immer auch zu halten people parasieren textdateien mit bash - es ist ineffizient. und Sie wissen nicht, wie groß diese Eingabedatei ist, so kann es wirklich schlecht sein :), und Bdfy, unter Berücksichtigung Ihrer SO-Reputation - wenn Sie Tag Python zu Ihrer Frage hinzufügen, werde ich arbeiten Python-Lösung, die ich denke ist besser zu benutzen als bash. – Drako
@Drako: Having said, 'awk' ist völlig in Ordnung für kleine Dateien – sjsam
@SJSAM Ich stimme zu, aber wenn die Eingabe wird 500MB oder mehr werden Sie wirklich mehr mit Python-Lösung glücklich :) deshalb, auch für kleine tendiere ich dazu Verwenden Sie die richtigen Tools, wenn möglich, weil Sie nie wissen, wann es wachsen kann :) – Drako
awk '{a[$1]=(a[$1]!="")?a[$1]","$2:$2}END{for(i in a){print i "\t" a[i]}}' file
key1 1212,32332
key2 1212,3232,3232
sollte es tun.
Wenn Sie vermeiden möchten, die Ergebnisse für die gesamte Datei zu puffern (z. B. wenn die Datei sehr groß ist), könnten Sie sort
und Pythons itertools.groupby
verwenden. Erstellen Sie ein Python-Skript wie folgt aus:
# group.py
import itertools, sys
for k, g in itertools.groupby(sys.stdin, lambda x: x.split()[0]):
print(k, ",".join([x.split()[1] for x in g]))
Dann laufen:
sort file | python group.py
key1 1212,32332
key2 1212,3232,3232
Ansonsten diese schnelle Perl Einzeiler sollte auch funktionieren, indem Sie Werte in einem Hash Akkumulieren:
perl -aE 'push @{$h{$F[0]}}, $F[1]; END {$"= ","; say "$_ @{$h{$_}}" for sort keys %h}' file
Ausgabe:
key1 1212,32332
key2 1212,3232,3232
es ist nicht rein sh/coreutils, betrachtet aber datamash für diese Aufgabe mit:
sed -r -e 's/[[:space:]]+/ /g' < infile.txt | datamash -t ' ' -s groupby 1 collapse 2
dies in bash möglich sein soll, aber ich würde vorschlagen, anstatt Ihr Gehirn zu brechen - bessere Tools verwenden, wenn Sie bash fragen - es Linux - hat definitiv python - benutze es - und die Aufgabe wird einfach. – Drako
awk und python-Tags aufgrund von Kommentaren zu meiner Antwort hinzugefügt. –