• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

Terminal - Wie sort und uniq richtig anwenden?

Sir Isaac

Jamba
Registriert
18.03.08
Beiträge
57
Ich habe folgende csv-Datei (unsortiert, natürlich deutlich länger):

22;33
33;55
22;55
55;55
11;22
33;22
44;44

und ich brauche die Häufigkeiten (sortiert, wieder csv-Datei):

11 0 1 0 0 0
22 0 0 1 0 1
33 0 1 0 0 1
44 0 0 0 1 0
55 0 0 0 0 1

in Worten:
- Akteur "11" hat keinen Kontakt mit Akteur 11, 33, 44, 55, aber Kontakt mit Akteur 22, deswegen die "1" im 2.Feld
- Akteur "22" hat keinen Kontakt mit Akteur 11, 22, 44, aber Kontakt mit Akteur 33 und 55
- ...

Das müsste im Terminal irgendwie mit den Befehlen sort und uniq gehen, wenn ich die aber in (fast) allen erdenklichen Varianten ausprobiere (bspw. sort -n test.csv), wird immer nur die letzte Zahl ausgegeben (hier: 44;44). Das heißt, mir fehlt noch die richtige Variante.

Mit more oder less zeigt das Terminal den gesamten Inhalt an: 22;33^M33;55^M22;55^M55;55^M11;22^M33;22^M44;44

Könnt ihr mir irgendwie auf die Sprünge helfen?


Ach ja: Arbeite mit Leopard 10.5.3, falls das wichtig sein sollte!?
 

quarx

Brauner Matapfel
Registriert
17.04.05
Beiträge
8.444
Brauchst Du jetzt nur die Anzahl der Kontakte pro Akteur oder die ganze Adjazenzmatrix (;))? Ich würde das eher mit einem perl-Skript machen.
 

Sir Isaac

Jamba
Registriert
18.03.08
Beiträge
57
Ich brauche die ganze Matrix, da ich diese später in ein weiteres Programm einlesen muss.
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Ich denke, mit sort und uniq kommst Du da nicht weit.

Code:
#!/usr/bin/perl
use strict;
use warnings;

my %verbindung;
while (<>) {
	tr/\012\015//d;
	next unless /;/;
	my($l,$r)= split /;/;
	++$verbindung{$l}{$r};
}
my(@akteure)= sort { $a <=> $b } keys %verbindung;
foreach my $l (@akteure) {
	print $l;
	foreach my $r (@akteure) {
		print ' ',(++$verbindung{$l}{$r})-1;
	}
	print "\n";
}

  1. Kopiere das in einen Texteditor Deiner Wahl
  2. Sichere es als (z.B.) "/Users/DeinBenutzername/zaehl"
  3. Öffne das Terminal
  4. gib ein
    Code:
    chmod +x zaehl
    ./zaehl [I][U]dateiname[/U][/I]
Für Dateiname setzt Du den Namen und Pfad der Datei ein, in Der Du Deine Liste stehen hast.
 
Zuletzt bearbeitet:

quarx

Brauner Matapfel
Registriert
17.04.05
Beiträge
8.444
Mit 'uniq' kann man ja nur direkt aufeinander folgende doppelte Zeilen eliminieren. Mit
Code:
cat test.csv | cut -d ';' -f 1 | sort | uniq
kannst Du zumindest mal die Liste der überhaupt auftretenden Akteure ermitteln (sofern jeder Akteur auch in der ersten Spalte auftaucht). Die Adjazenzmatrix aufbauen würde ich aber wie gesagt lieber in einem Perlskript. :eek:

Edit: boah, Skeeve war aber fix.
 

Sir Isaac

Jamba
Registriert
18.03.08
Beiträge
57
Danke schon mal für eure Mühe(n).

Wenn ich folgendes eingebe:
Code:
chmod +x zaehl ./zaehl ./test.csv >testmatrix.csv
dann ist die erzeugte Datei immer leer. Liegt der Fehler im Code oder an mir?
 

Sir Isaac

Jamba
Registriert
18.03.08
Beiträge
57
Okay, erstes Problem gelöst - Danke.

Wenn ich entsrechende Befehle eingebe kommt als Fehlermeldung:
Code:
./zaehl: line 1: {rtf1ansiansicpg1252cocoartf949cocoasubrtf330: command not found
./zaehl: line 2: syntax error near unexpected token `}'
./zaehl: line 2: `{\fonttbl\f0\fswiss\fcharset0 Helvetica;}'

Was der erste Fehler zu bedeuten hat, weiß ich nicht.
Den zweiten Fehler werde ich mal versuchen, ausfindig zu machen. Wer mir helfen mag, sei herzlich dazu eingeladen :).
Der dritte Fehler ist wahrscheinlich irrelevant. Oder?

Wie schon mal gesagt: Danke!
 

tomsie

Bismarckapfel
Registriert
25.11.06
Beiträge
76
Wenn ich entsrechende Befehle eingebe kommt als Fehlermeldung:
Code:
./zaehl: line 1: {rtf1ansiansicpg1252cocoartf949cocoasubrtf330: command not found
./zaehl: line 2: syntax error near unexpected token `}'
./zaehl: line 2: `{\fonttbl\f0\fswiss\fcharset0 Helvetica;}'

Was der erste Fehler zu bedeuten hat, weiß ich nicht.
Den zweiten Fehler werde ich mal versuchen, ausfindig zu machen. Wer mir helfen mag, sei herzlich dazu eingeladen :).
Der dritte Fehler ist wahrscheinlich irrelevant. Oder?
Du hast die Datei anscheinend mit TextEdit als "Formartierter Text (RTF)" gespeichert. Versuch mal, nur eine normale Textdatei daraus zu machen. Z.B. indem du die Datei mit Smultron erstellst.
 

Sir Isaac

Jamba
Registriert
18.03.08
Beiträge
57
Danke für eure Hilfe. Ich habe das Vorgehen soweit kapiert.

Leider ist das Output-File immer leer. Auch wenn ich vorher mittels
Code:
tr '\r' '\n' <macfile >unixfile
das File "bearbeite", so dass der Output des Befehls more (bzw. less) keine ^M mehr beinhaltet, funktioniert das Skript nicht. Und leider bin ich nicht in der Lage, den Fehler ausfindig zu machen :-[.

Falls jemand noch eine Idee hat, ist diese herzlich willkommen und ich würde mich riesig freuen :-D, denn das erspart mir doch ein bisschen Handarbeit.
 

quarx

Brauner Matapfel
Registriert
17.04.05
Beiträge
8.444
Das Perl-Skript von Skeeve ist auf Kodierung des Zeilenendes mit einem Zeichen (z.B. unter Unixen wie Mac OS X mit LF) ausgelegt, da der chomp()-Befehl genau ein Zeichen löscht. Ich sehe da drei Alternativen für Dich, wenn die Daten in einer DOS- bzw. Windows-Kodierung mit zwei Zeilenende-Zeichen (CR+LF) vorliegen:
  • vorher genau ein Zeichen löschen, am besten das CR (aka \r)...
    Code:
    cat test.csv | tr -d '\r' | ./zaehl
    Das funktioniert z.B. mit den DOS-kodierten Beispieldaten aus Post #1, siehe Attachment
  • die Quelldaten vorher durch ein nachinstalliertes recode jagen, das gibt's zum Bleistift bei MacPorts
  • dem Perl-Skript ein zusätzliches chomp() verpassen (dann funktioniert es natürlich nicht mehr mit der Zeichencodierung vom Mac)
 

Anhänge

  • test.csv.zip
    185 Bytes · Aufrufe: 65

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
chop schneidet ein Zeichen ab.
chomp schneidet ein Zeilenende ab, so es vorhanden ist.
Wenn nun CR LF als Zeilenende da stehen, dann sollten man einfach $/ entsprechend setzen oder mit folgendem anstelle von chomp arbeiten:
tr/\012\015//d
Letzteres trage ich jetzt oben ein.