1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Terminal - Wie sort und uniq richtig anwenden?

Dieses Thema im Forum "Unix & Terminal" wurde erstellt von Sir Isaac, 31.05.08.

  1. Sir Isaac

    Sir Isaac Jamba

    Dabei seit:
    18.03.08
    Beiträge:
    56
    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!?
     
  2. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Brauchst Du jetzt nur die Anzahl der Kontakte pro Akteur oder die ganze Adjazenzmatrix (;))? Ich würde das eher mit einem perl-Skript machen.
     
  3. Sir Isaac

    Sir Isaac Jamba

    Dabei seit:
    18.03.08
    Beiträge:
    56
    Ich brauche die ganze Matrix, da ich diese später in ein weiteres Programm einlesen muss.
     
  4. Skeeve

    Skeeve Pomme d'or

    Dabei seit:
    26.10.05
    Beiträge:
    3.121
    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.
     
    #4 Skeeve, 31.05.08
    Zuletzt bearbeitet: 01.06.08
  5. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    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.
     
  6. Sir Isaac

    Sir Isaac Jamba

    Dabei seit:
    18.03.08
    Beiträge:
    56
    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?
     
  7. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Letzteres, es fehlt ein Return zwischendurch. Erst mit
    Code:
    chmod +x zaehl
    das Skript ausführbar machen und danach ausführen mit
    Code:
    ./zaehl ./test.csv >testmatrix.csv
     
  8. Sir Isaac

    Sir Isaac Jamba

    Dabei seit:
    18.03.08
    Beiträge:
    56
    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!
     
  9. tomsie

    tomsie Bismarckapfel

    Dabei seit:
    25.11.06
    Beiträge:
    76
    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.
     
  10. Sir Isaac

    Sir Isaac Jamba

    Dabei seit:
    18.03.08
    Beiträge:
    56
    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.
     
  11. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    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:

  12. Skeeve

    Skeeve Pomme d'or

    Dabei seit:
    26.10.05
    Beiträge:
    3.121
    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.
     

Diese Seite empfehlen