peddy
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Hallo, ich möchte Daten aus zwei CSV-Dateien zusammenführen. Datei 1 hat das Format:
Nachname,Vorname,Loginname Datei 2 hat das Format:
Nachname,Vorname, Geburtstag Die Ausgabedeit soll dieses Format haben:
Nachname,Vorname,Loginname,Geburtstag Leider sind in Datei 2 weniger Einträge als in Datei 1. Man müsste also Zeile für Zeile durchgehen und nachsehen, ob man eine Person die in Datei 1 steht auch einen Eintrag in Datei 2 hat. In diesem Fall soll der Beburtstag übertragen werden. Wie würdet ihr das machen? Bearbeitet von rklm: Codeblock für Formate
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Man könnte das z.B. mit Python3 lösen (unter der Voraussetzung, dass die Kombination aus Vorname und Nachname ein eindeutiges Merkmal ist und die Felder in den CSV-Dateien keinen Whitespace am Anfang oder Ende haben, der zu den Daten gehört):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | #!/usr/bin/env python3
import fileinput
from collections import defaultdict
# file with last_name,first_name,login_name
logins = 'logins.csv'
# file with last_name,first_name,birthday
birthdays = 'birthdays.csv
data = defaultdict(lambda: defaultdict(dict))
for line in fileinput.input(logins):
last_name, first_name, login_name, *_ = line.strip().split(',')
data[last_name.strip()][first_name.strip()]['login_name'] = login_name.strip()
for line in fileinput.input(birthdays):
last_name, first_name, birthday, *_ = line.strip().split(',')
data[last_name.strip()][first_name.strip()]['birthday'] = birthday.strip()
with open('output.csv', 'w') as output:
for last_name, keys in data.items():
for first_name, p_data in keys.items():
print(last_name, first_name,
p_data.get('login_name', 'N/A'),
p_data.get('birthday', 'N/A'),
sep=',', file=output)
|
|
peddy
(Themenstarter)
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Dein Script hat sehr gut funktioniert. 1000 mal danke 👍
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Ansonsten lohnt sich vielleicht die Verwendung von join, einem Unixfossil.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Kann man mit join zwei Felder (in dem Fall Vor- und Nachname) für den Vergleich nutzen (außer die Dateien vorab anders aufzubereiten)? Sowas würde natürlich gehen, aber besonders gut nachvollziehbar ist das IMHO nicht...
join -a 1 -t',' -j1 <(sed 's/,/\t/' logins.csv) <(sed 's/,/\t/' birthdays.csv) | sed -e 's/\t/,/;s/^\([^,]\+,\)\{2\}[^,]\+$/&,N\/A/'
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
seahawk1986 schrieb: Man könnte das z.B. mit Python3 lösen (unter der Voraussetzung, dass die Kombination aus Vorname und Nachname ein eindeutiges Merkmal ist und die Felder in den CSV-Dateien keinen Whitespace am Anfang oder Ende haben, der zu den Daten gehört):
Da ist awk aber deutlich eleganter: | $ cat 1
a,b,c
d,e,f
$ cat 2
a,b,D
e,f,G
$ awk -F , 'FNR == NR {data[$1,$2]=$0} FNR != NR {x=data[$1,$2]; if (x) print x FS $3}' 1 2
a,b,c,D
|
☺ user_unknown schrieb: Ansonsten lohnt sich vielleicht die Verwendung von join, einem Unixfossil.
Oh, wieder was gelernt. Immerhin kann das Fossil mit Null-terminierten Zeilen umgehen. 👍
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
seahawk1986 schrieb: Kann man mit join zwei Felder (in dem Fall Vor- und Nachname) für den Vergleich nutzen (außer die Dateien vorab anders aufzubereiten)? Sowas würde natürlich gehen, aber besonders gut nachvollziehbar ist das IMHO nicht...
join -a 1 -t',' -j1 <(sed 's/,/\t/' logins.csv) <(sed 's/,/\t/' birthdays.csv) | sed -e 's/\t/,/;s/^\([^,]\+,\)\{2\}[^,]\+$/&,N\/A/'
Ich habe es auch erst 1-2 Mal benutzt, und musste ziemlich rumexperimentieren, um die Syntax zu verstehen, also bitte selbst versuchen oder andere Hilfsquellen bemühen.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
rklm schrieb: Da ist awk aber deutlich eleganter: | $ cat 1
a,b,c
d,e,f
$ cat 2
a,b,D
e,f,G
$ awk -F , 'FNR == NR {data[$1,$2]=$0} FNR != NR {x=data[$1,$2]; if (x) print x FS $3}' 1 2
a,b,c,D
|
Ich hatte das so verstanden, dass die beiden Dateien zusammengeführt werden sollen (was das Python-Skript macht und er OP als Lösung akzeptiert hat) und nicht nur die Zeilen aus der ersten Datei übernommen werden sollen, für die es einen passenden Eintrag in der zweiten Datei gibt - für deine Beispieldaten würde ich dann so etwas in der Art als Ergebnis erwarten (wenn man Felder mit leeren Daten leer lässt statt da wie das Python-Skript "N/A" rein zu schreiben):
a,b,c,D
d,e,f,
e,f,,G
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
seahawk1986 schrieb:
Ich hatte das so verstanden, dass die beiden Dateien zusammengeführt werden sollen (was das Python-Skript macht und er OP als Lösung akzeptiert hat)
Recht hast Du. Das fehlte noch | $ awk -F , 'FNR == NR {data[$1,$2]=$0}
FNR != NR {x=data[$1,$2]; if (x) {print x FS $3; read[$1,$2]=1} else print $1 FS $2 FS FS $3}
END {for (i in data) {x=data[i]; if (x && !read[i]) print data[i] FS}}' 1 2
a,b,c,D
e,f,,G
d,e,f,
|
|