Neulich bei der Userverwaltung (genauergesagt Import einer CSV Liste) eines

groesseren Systems traf ich auf den Bedarf, einer Datei mit Anmeldenamen
noch die zugehoerigen Infos zu den jeweiligen Namen aus anderen Dateien
hinzu zufuegen. Anbei ein Beispiel …

Ich habe eine Datei mit Namen …

Datei mit Format ANMELDENAME

heino@sora:~/p/lugmoe/blog_paste$ cat namen
adam
erwin
igor
otto
uriel

… und eine weitere Datei mit Raumnummern.

Datei mit Format ANMELDENAME, VOLLER NAME, RAUMNUMMER

heino@sora:~/p/lugmoe/blog_paste$ cat raum
adam,Adam Evans,44a
erwin,Erwin Derwish,33e
igor,Igor Frankenstein,11i
otto,Otto Fant,00o
siegfried,Siegfried Nibel,55s <– ist nicht bei den Anmeldenamen
uriel,Uriel Hell,666u
zorro,Zorro Gonzales,22z <– ist nicht bei den Anmeldenamen

PASTE
—–

Beide Dateien sind nach dem ersten Feld sortiert (alphabetisch).
Mit paste behandele ich die Dateien wie Spalten, die ich in einer
neuen Datei zusammen fuehren will:

heino@sora:~$ paste namen raum
adam adam,Adam Evans,44a
erwin erwin,Erwin Derwish,33e
igor igor,Igor Frankenstein,11i
otto otto,Otto Fant,00o
uriel siegfried,Siegfried Nibel,55s
uriel,Uriel Hell,666u
zorro,Zorro Gonzales,22z

Das ist schon fast zu gebrauchen, aber leider haben wir einmal eine kleine
Liste mit Leuten die mich interessieren und eine „grosse“ Liste mit allen
Mitarbeitern, aus denen ich nicht alle brauche. paste haengt die
erste Zeile der zweiten Datei an die erste Zeile der ersten Datei. Klappt,
solange alles sortiert ist und die Anzahl der Zeilen gleich ist. Hier reicht
die Intelligenz von paste nicht ganz aus.

JOIN
—-

join nutzt das gemeinsame Feld, um eine korrekte Zuordnung zu kriegen
und die ueberfluessigen Eintraege zu ignorieren. Mich interessieren ja nur die
Leute aus meiner Abteilung. Die sind in der Liste mit den Anmeldenamen.

heino@sora:~$ join -t, namen raum
adam,Adam Evans,44a
erwin,Erwin Derwish,33e
igor,Igor Frankenstein,11i
otto,Otto Fant,00o
uriel,Uriel Hell,666u

Mit -t, gebe ich an, dass die Felder durch ein , als
getrennt zu behandeln sind. So sieht das ganze schon brauchbar aus. Ich habe
meine beiden Listen vereint, ohne ueberfluessige Zeilen Eintrage und ohne
doppelte Felder (Anmeldenamen) wie bei paste.

Allerdings arbeitet join hier mit sortierten Dateien.
Jede Zeile wird mit der gleichen Zeile der anderen Datei verglichen und nach
einem gemeinsamen Feld gesucht. join nimmt als Default das erste Feld
als gemeinsames. Falls die Dateien nicht sortiert waeren, gaebe es schon
Probleme und join haette weniger Treffer. Also ein Fall fuer …

SORT
—-
Um Dateien anhand eines bestimmten Feldes zu sortieren nimmt man einfach
sort. Hier eine weitere Datei mit Telefon Nummern zugeordnet zum
Anmeldenamen:

heino@sora:~$ cat telefon
00000,otto
11111,igor
22222,zorro
33333,erwin
44444,adam
55555,siegfried
666,uriel

Diese Datei ist nach dem ersten Feld sortiert (der Telefonnummer) und das gemeinsame
Feld ist in der 2 Spalte. Um diese Datei mittels join mit meinen
gesuchten Personen korrekt zu vereinen, brauche ich ersteinmal eine nach dem
2. Feld sortierte Liste:

heino@sora:~$ sort -k2 -t, telefon
44444,adam
33333,erwin
11111,igor
00000,otto
55555,siegfried
666,uriel
22222,zorro

Mit -k2 gebe ich das 2. Feld als Sortierfeld an.

Mit -t, gebe ich den Feldtrenner , an.

Diesen OUTPUT kann aich in eine Datei leiten oder ich nutze sort und
join kombiniert ueber PIPE auf der SHELL …

heino@sora:~$ sort -k2 -t, telefon | join -t, -1 1 -2 2 namen –
adam,44444
erwin,33333
igor,11111
otto,00000
uriel,666

Mit -t, gebe ich wieder den Feldtrenner an.

Mit  wird hier von STDIN gelesen, wegen der Sortierung der
Telefon Liste.

Mit -1 1 und -2 2 gebe ich an, dass in Datei 1 das erste Feld genommen wird
und in Datei 2 (kommt hier ueber STDIN weil ich  angegeben habe) das
zweite Feld. Schon habe ich eine Liste mit Anmeldenamen und Telefonnummern.
Zur korrekten Ansprache der Leute braeuchte ich noch den vollen Namen dazu …

erstelle eine weitere Datei

heino@sora:~$ join -t, namen raum > nara
heino@sora:~$ cat nara
adam,Adam Evans,44a
erwin,Erwin Derwish,33e
igor,Igor Frankenstein,11i
otto,Otto Fant,00o
uriel,Uriel Hell,666u

heino@sora:~$ sort -t, -k2 telefon | join -t, -1 1 -2 2 nara –
adam,Adam Evans,44a,44444
erwin,Erwin Derwish,33e,33333
igor,Igor Frankenstein,11i,11111
otto,Otto Fant,00o,00000
uriel,Uriel Hell,666u,666

Nun habe ich eine brauchbare Liste … inspiriert wurde ich von meinem
aktuellen Bedarf dieser Liste und der
Seite: Lesser-known Linux commands: join, paste, and sort

CUT

Ergaenzender Vorschlag von Nobby: eine Auswahl relevanter Spalten
ausgeben

Mit cut kann ich aus der Liste die vollen Namen und deren
Telefonnummern extrahieren.

Nur voller Name mit Telefonnummer

heino@sora:~$ sort -t, -k2 telefon | join -t, -1 1 -2 2 nara – | cut -f 2,4 -d“,“
Adam Evans,44444
Erwin Derwish,33333
Igor Frankenstein,11111
Otto Fant,00000
Uriel Hell,666

-f 2,4 gibt an, nur die 2. und die 4. Spalte auszuschneiden

-d „,“ bestimmt den Feldtrenner

29. August 2007 – 8:30 — heino