Verantwortlich: Prof. Anja Feldmann, Dr. Manfred Jobmann, Nils Kammenhuber, Stefan Kornexl
Wir bemühen uns, in dieser FAQ folgende Kennzeichnung zu verwenden:
print-Anweisungen aus.#!/usr/bin/perl
mein Perlskript nicht direkt aufrufen.sort benutzt werden?log="xy" klappt nicht bei
Histogrammen!Möglicherweise gibt es irgendwelche seltsamen Cache-Probleme. Klicke in Deinem Browser auf den Reload-Button, während Du gleichzeitig die Shift- bzw. die Control-Taste gedrückt hältst. Dann sollte der Browser auf jeden Fall die neueste Version laden.
Am Lehrstuhl sind Transponderkarten erhältlich, die die Tür zum Praktikumsraum jederzeit öffnen können. Die Ausgabe der Karten erfolgt an die Praktikumsteilnehmer nachdem die Registrierung abgeschlossen ist.
Ansonsten geh' in den Flur des Lehrstuhl Feldmann und frag' irgendjemanden der Anwesenden, ob er/sie Dir mit seinem/ihrem Transponder den Praktikumsraum öffnen kann.
Sollte keiner mehr dort sein, bleibt Dir wohl nichts anderes übrig, als z.B. in die "Sunhalle" zugehen und Dich von dort aus remote einzuloggen.
Einfach mit ssh auf irgendeinen der folgenden Rechner einloggen:
viper.net.informatik.tu-muenchen.de slowworm.net.informatik.tu-muenchen.de housesnake.net.informatik.tu-muenchen.de seasnake.net.informatik.tu-muenchen.de adder.net.informatik.tu-muenchen.de cobra.net.informatik.tu-muenchen.de boa.net.informatik.tu-muenchen.de copperhead.net.informatik.tu-muenchen.de
(Bitte nur in Ausnahmefällen auf python einloggen - das ist der NFS-Server, und wenn man dort rechenintensive Programme laufen lässt, dann leidet die Filesystem-Performance für alle anderen.)
Bis der password:-Prompt kommt, kann es u.U. eine Zeitlang dauern, also nicht die Geduld verlieren.
Wenn Du einen Laptop hast, kannst Du ihn einfach an eines der freien Ethernetkabel anschließen, die an den Switches auf den Praktikumstischen dranhängen und dann mit Deinem Laptop arbeiten. (Außerdem sollte eigentlich das Funk-LAN im Gebäude funktionieren.)
Siehe auch Wie greife ich auf die Rechner im Praktikumsraum zu?
Die Lösungen müssen...
Angenommen, mein eigenes Login lautete meinLogin und das meines Teampartners partnerLogin. Die Uhrzeit sei 15:00h (und 27 Sekunden). Dann gebe ich meine Lösung für die 1. Übung folgendermaßen ab:
meinLogin@viper> mkdir
meinLogin_partnerLogin
meinLogin@viper> cp loesungsfile1
loesungsfile2 loesungsfile3 usw meinLogin_partnerLogin/
meinLogin@viper> date +%H%M%S
150027
meinLogin@viper> tar -czf
meinLogin_partnerLogin_150027.tgz
meinLogin_partnerLogin/
meinLogin@viper> cp
meinLogin_partnerLogin_150027.tgz
/home/prak/abgaben/1.uebung/
meinLogin@viper> chmod 640
/home/prak/abgaben/1.uebung/meinLogin_partnerLogin_150027.tgz
meinLogin@viper>
Schon abgegebene Lösungen können bis zur Abgabedeadline upgedatet werden (d.h., man kann z.B. sicherheitshalber schon einige Tage vor der Deadline eine halbfertige Lösung abgeben, ohne Nachteile zu erwarten.) Dazu gibt man einfach nochmal eine komplette Lösung wie oben beschrieben mit aktuellem Datum ab.
Siehe auch Welche Sprachen sind erlaubt?
Ab sofort ist für jedes Team eine Unix-Gruppe eingerichtet worden. Damit ist es möglich, gemeinsam an Code zu arbeiten und ihn gleichzeitig vorm Abschreiben zu schützen.
Falls Du Dich bislang durch Dein Informatikstudium durchgemogelt
hast, ohne Erfahrung mit Unix-artigen Betriebssystemen gesammelt zu
haben (pfui, pfui!:-), hier ein kleines Beispiel:
Angenommen, Dein Login sei wutzengruber und das Deines
Teampartners podrak. Du möchtest Dein Verzeichnis
~/blatt23/ für ihn freigeben. Das geht
folgendermaßen:
wutzengruber@boa$ id wutzengruber uid=23456(wutzengruber) gid=20052(ws2005) groups=20052(ws2005),21017(team18) wutzengruber@boa$ id podrak uid=23457(podrak) gid=20052(ws2005) groups=20052(ws2005),21017(team18) wutzengruber@boa$ chgrp team18 ~/blatt23 wutzengruber@boa$ chmod g+w,o-rwx ~/blatt23 wutzengruber@boa$ chmod g+sw,o-rwx ~/blatt23 wutzengruber@boa$ ls -lsd ~/blatt23 0 drwxrws--- 2 wutzengruber team18 6 2018-11-11 12:01 blatt23/
Nun kann podrak auf Dein Verzeichnis auch schreibend zugreifen:
podrak@adder$ echo hallo > /home/wutzengruber/blatt23/testdatei
Bei Unklarheiten: man chgrp bzw. man chmod und man id.
Wenn Du uns Textdateien abgibst, z.B. die bei jeder Abgabe obligatorische README.txt, oder auch (wenn Du eine Frage hast) per E-Mail schickst, dann stelle bitte sicher, dass alle Textdateien in einem der folgenden (beliebigen) Formate vorliegen und die korrekte Dateinamensendung aufweisen:
Für Grafikdateien sind folgende Formate erlaubt:
eingerichtet, über welche Du alle anderen
Praktikumsteilnehmer erreichen kannst."GNU R". Oder nach splus
bzw. s-plus anstatt nach R (denn R
und Splus sind sehr weitgehend kompatibel
zueinander).| Befehl | liefert |
|---|---|
| man perl | generelle Übersicht |
| man perlsyn | Syntax von Perl |
| man perlfunc | die in Perl eingebauten Funktionen |
| man perlre | Reguläre Ausdrücke in Perl |
| man perldata | Infos zu den Datentypen von Perl |
| man perlrun | u.A. trickreiche Parameter beim Aufruf von Perl, die einem viel
Schreibarbeit sparen können
(z.B. perl -n -a)
|
| ... | ... |
| man perltoc | Übersicht über die anderen Manpages zum Thema Perl |
| man perlref | Wie man in Perl Referenzen benutzt und damit auch komplexere Datenstrukturen (Arrays in Hashes, Hashes in Arrays usw.) anlegen kann |
#!/usr/bin/perl mein Perlskript nicht direkt
aufrufen.#!/usr/bin/perl.#! und /usr/bin/perl darf kein
Leerzeichen stehen.Das ist etwas trickreich, denn so einfach wie in Perl geht es leider nicht. Eine Möglichkeit ist folgende:
#!/bin/sh exec /usr/bin/R --vanilla << EOF ...ab hier dann die Zeilen Deines R-Skriptes
Dann kannst Du das R-Skript (welches dann eigentlich
ein sh-Skript ist) einfach mit ./meinRskript
aufrufen. Vorher musst Du natürlich noch Ausführ-Rechte
mit chmod +x meinRskript gegeben haben.
Möglicherweise gibt es elegantere Alternativen als die hier
beschriebene, zu einem selbst ausführbaren R-Skript zu
kommen.
Eine Alternative ist, Dein R-Skript ohne den
#!/bin/sh usw. abzuspeichern und es stattdessen mit
R --vanilla < meinRskript aufzurufen.
Wenn Du bereits eine R-Session laufen hast und nun ein
File ausführen möchtest, dann erreichst Du das mit dem
Befehl
> source("meinRskript", echo=T)
Sofern nicht genauer spezifiziert, sind folgende Sprachen erlaubt:
zcat datei.gz | java mein.tolles.Programm | ./meinperlskript | perl -n -e '...(mein Perl-Einzeiler...)' | sort
Grundsätzlich gilt: Deine Programme müssen ohne Änderungen, Umkonfigurationen und sonstige vorbereitenden Arbeiten auf den Schlangen-Rechnern lauffähig sein.
Falls Dein Programm dennoch solche vorbereitenden Arbeiten
erfordert (z.B. Setzen von $CLASSPATH bei
Java-Programmen, oder Umleiten der Ausgabe Deines Programmes in
einen Shellbefehl wie z.B. sort, usw.), dann schreibe
einfach ein kurzes Shellskript, das diese Aufgaben automatisch
erledigt.
Siehe auch: Warum soll ich überhaupt Perl lernen?, Welche UNIX-Tools kann ich noch verwenden?.
Fast alle der Datenquellen, mit denen ihr arbeitet, sind Textdateien. Zum Bearbeiten dieser Dateien gibt es eine ganze Reihe an Unix-Kommandos, mit denen man (ohne eine Zeile Perl zu schreiben) auch schon recht viel erledigen kann. Vermutlich ist es sinnvoll, sich folgende Kommandos und ihre Manpages genauer anzuschauen:
Darüberhinaus kann man sich auch kompliziertere Pipes mit
Hilfe sogenannter named Pipes (auch FIFOs genannt)
bauen. Wenn einem beispielsweise
befehl1|befehl2|befehl3|... nicht ausreicht und man z.B.
"mehrere Pipes parallel" legen möchte, dann kann man sich eine
named pipe anlegen. Das ist sozusagen eine spezielle Datei,
die [fast] keinen Platz auf der Platte belegt, und mit der man
Eingaben von einem schreibenden Prozess in einen lesenden Prozess
umleiten kann. Oder man stellt es sich so vor, dass man dem
|-Symbol einen Dateinamen verpasst und statt
befehl1|befehl2 dann z.B. befehl1>meinepipe
und befehl2<meinepipe verwenden kann. Aber
natürlich geht es auch viel flexibler, da man die Pipes [fast]
überall anstelle von Dateien einsetzen kann, was manchmal sehr
elegant sein kann. Ein Beispiel:
meinLogin@viper> mkfifo /tmp/meinefifo
Damit legst Du eine neue Pipe namens meinefifo im
Verzeichnis /tmp an.
meinLogin@viper> ls > /tmp/meinefifo &
[1] 12345
Das & bewirkt, dass der ls-Befehl im
Hintergrund abläuft. Die Shell zeigt an, dass dieser
Hintergrundprozess die Prozessnr. 12345 erhalten hat. Das
ls versucht jetzt, in die Fifo zu schreiben; allerdings
liest momentan niemand aus der Fifo, so dass das ls
ersmtal blockiert wird.
meinLogin@viper> cat
/tmp/meinefifo
bin Desktop Kruscht mail netzsaug src tmp (...und was sonst
noch so im Homedir drin ist)
[1]+ Done ls >/tmp/meinefifo
meinLogin@viper>
Das cat hat aus der Fifo rausgelesen, und somit konnte das
im Hintergrund wartende ls terminieren, was die Shell auch
anzeigt ("[1]+ Done ls...").
Mit solchen Fifo-Tricks kann man z.B. auch kompliziertere, verzweigte Pipelines bauen, in der Art von
befehl1 -o fifo | befehl2 | befehl3 | befehl4 -r fifo | befehl5oder man kann "Pipeline-Ringe bauen", z.B. so:
befehl1 < ringfifo | befehl2 | befehl3 | befehl 4 > ringfifo
Hinweis: Man kann Fifos allerdings nicht dazu benutzen, um auf einem Rechner in die Fifo reinzuschreiben und auf einem anderen Rechner daraus zu lesen. (Dazu verwendet man i.A. TCP-Sockets.)
Angenommen, das Verzeichnis heiße dir. Dann:
Anmerkung für Leute, die die Übungen an einem anderen Rechner (z.B. zuhause oder sunhalle) erstellen: Es gibt verschiedene Versionen von tar - verwende daher unbedingt eine Version, die zu der auf den Praktikumsrechnern defaultmäßig installierten kompatibel ist!
Es ist ein mit dem Befehl gzip komprimiertes File. Zum Ausgeben auf Standardausgabe benutze entweder
In Perl kannst Du es recht trickreich auslesen mit
open(DATEIHANDLE, "zcat dateiname|")
so dass das File also beim Auslesen gleich automatisch
dekomprimiert wird.
Du brauchst nicht immer ein Programm zu schreiben; Du kannst manchmal wichtige Informationen durch eine einzige Zeile in der Shell herausbekommen.
Benutze hierzu die sogenannten Pipes. Wenn z.B. der Inhalt der Datei zu groß ist, kannst Du die Ausgabe des Dekompressionskommandos in den Pager less pipen, und zwar mit zcat dateiname.gz | less.
Du kannst diese Pipes sogar schachteln, was sie sehr, sehr
mächtig macht. Ein Beispiel:
zcat name.gz | grep "http" | sort -n -r -k 3 | uniq | head >ausgabe.txt
Wohlgemerkt: Das ist eine einzige Zeile, die man in die Shell eintippt. Diese recht komplexe Aufgabe wurde also komplett ohne irgendein Programm oder Skript gelöst.
zcat logfile.gz | perl -e 'while(<>){s/\s+/ /g;@l=split;@f=split("/",$l[3]);$p{$f[1]}++;}foreach $i (sort keys %p) {print "$i:$p{$i}\n";}'
Natürlich ist dieser Einzeiler schrecklich unübersichtlich und somit quasi unlesbar. Daher das ganze nochmal in kommentierter Form:
| zcat logfile.gz | Ausgabe des Logfiles auf die Standardausgabe (vgl. oben) |
| | | Umleiten von Standardausgabe auf Standardeingabe |
| perl -e | Aufruf von Perl mit der restlichen Kommandozeile als auszuführendes Skript |
| while() {} | While-Schleife |
| <> | Zeilenweises Lesen der Standardeingabe (in Variable
$_) |
| while(<>) {} | Durchlaufen aller Zeilen der Standardeingabe |
| s/\s+/ /g; | globales Ersetzen von mehreren Spaces durch ein Space |
| @l=split; | Aufspalten einer Zeile in ein Array namens l mit
dem Space als Trennzeichen |
| @f=split ("/", $l[3]); | Aufspalten des 4ten Wortes (Trennzeichen ist
"/") |
| $p{$f[1]}; | Benutzt 2ten Eintrag von f als Hash in Hashtabelle
p |
| $p{$f[1]}++; | Automatisches Erhöhen des Wertes in der Hashtabelle |
| keys %p | Liste aller Hashes der Hashtabelle p
Hash := Hashkey
|
| sort keys %p | Sortiere die obige Liste von Hashes |
| foreach $i (sort keys %p) {} | Für jeden Eintrag (der dann bei jedem Durchlauf jeweils in
der Variable i gespeichert wird) in der sortierten
Liste von Hashes |
| print "$i:$p{$i}\n"; | Gib den Wert von i und den Wert des Hashes
aus |
Und wie Du siehst, kann man Perl also auch "on-the-fly" benutzen, also ohne eine extra Skriptdatei anzulegen. Das ist zwar gut, wenn man schnell etwas ausprobieren will, wird aber natürlich schnell unübersichtlich - so wie hier. Also muss man solche "Einzeiler" dann gut dokumentieren.
Eine Beispielskriptdatei für ein sehr simples Perlskript, welches seine Eingabe zeilenweise einliest, die Werte als Zahlen interpretiert, mit 2 multipliziert und die neuen Werte ausgibt, findest Du hier. Einfach mit chmod +x beispiel.pl ausführbar machen, mit cat | ./beispiel.pl starten, Zahlen eingeben, und das ganze mit Control-D (nicht C!) beenden.
Mehr Infos, wie man Perl trickreich aufrufen kann und sich dadurch eine Menge Schreibarbeit sparen kann, findest Du übrigens auf der Manpage man perlrun.
Damit ist gemeint, dass alle Werte durch ihren Logarithmus ersetzt werden sollen. Es geht dabei lediglich um eine nichtlineare Darstellung, bei dem die Abstände in der Skala dem logarithmischen Gesetz x = log y folgen, sprich: die Abstände 1 bis 2, 2 bis 4, 4 bis 8 usw. sind in der Grafik jeweils gleich groß. Wie man sich leicht klar macht, ist es dabei egal, welche Basis man für den Logarithmus wählt.
Du musst nicht, wir empfehlen es Dir nur. Einer der zahlreichen positiven Aspekte von Perl ist dabei auch der, dass man schon mit nur wenigen Kenntnissen der Sprache sehr weit kommt. Perls Motto ist there's more than one way to do it, was man auch so interpretieren kann, dass man auch schon als Anfänger in Perl "alles" machen kann, nur dass eben ein Perl-Profi die Sachen z.T. schneller und eleganter hinbekommt.
In diesem Praktikum wirst Du Perl insbesondere gebrauchen können für:
Auch im Alltag wird Dir Perl später gute Dienste leisten. Übrigens sind viele sog. CGI-Skripte im WWW-Bereich in Perl geschrieben.
Download hier.
print-Anweisungen aus.Du kannst das Autoflush mit $|=1 (möglichst zu
Beginn des Programms) einschalten... meistens löst das das
Problem.
Es darf maximal ein Blatt nicht bearbeitet werden.
Solche Zeilen einfach ignorieren: weder Division durch 0 noch log(0) sind definiert.
Bei unserem Systemverwalter, Alexander Lüdtke, allerdings nur, wenn er da ist. Andere Personen können keine Karten ausgeben. Bitte bringe etwas Geld mit, da wir ein Pfand verlangen müssen.
sort() benutzt
werden?Ja, die Perl-sort()-Funktion oder das Unixkommando
sort dürfen verwendet werden.
Die Zeitangaben sind in Sekunden (UNIX-Timestamp, also Sekunden seit 1.1.1970).
Was weiß denn ich!? Keine Ahnung!!
Versuch' mal, die letzte Ziffer der Matrikelnummer wegzulassen. Uns ist intern ein Fehler beim Übermitteln der Daten passiert.
Normalerweise würde man zum Bilden des durchschnittlichen Mittelwertes für die Downloadraten den Wert (1/n)∑i(Größei / Zeit i) berechnen. Damit sind aber Downloads kleiner Dateien genauso stark gewichtet wie die großer Dateien. Wir betrachten die Sache erstmal allgemein und weisen dem i-ten Wert das Gewichti zu. Also berechnet man sum;i(Gewichtix(Größe i / Zeiti)). Das mit (1/n) vor der Summe stimmt dann natürlich nicht mehr und muss entsprechend (wie?) angepasst werden. In unserem Fall ist in der Aufgabenstellung definiert, dass als Gewichti := Größei zu verwenden ist.
Eines der Perl-Mottos lautet: "There's more than one way to do
it." Genau das ist hier der Fall. Eine Möglichkeit ist,
split() anzuwenden, und zwar vermutlich mehrfach. Eine
andere Möglichkeit ist die, mit Hilfe regulärer
Ausdrücke zu matchen:
/blablabla(willichhaben)blubbblubb/ liefert bei einem
Match den Ausdruck in Klammern in $1. Eine dritte
Möglichkeit ist, mit Hilfe regulärer
Ersetzungsausdrücke unerwünschte Teile zu "verdampfen":
s/willichnichtsehen// bzw.
s/willichnichtsehen//g.
Damit ist gemeint, dass man zunächst die Werte neu berechnet und dann eine kurze schriftliche Erklärung abgibt, weshalb sich welche Werte wie ändern.
log="xy"
klappt nicht bei Histogrammen!Stimmt. Man hat eben nicht alles mundfertig in R, und Du sollst ja auch ein wenig lernen, mit R umzugehen. Hier einige Tips:
hist() macht nicht einfach nur einen Plot; es
liefert auch ein Objekt zurück. Mach mal
x<-hist(...) und untersuche das Objekt
x.hist() nur zu generieren, das eigentliche Plotten aber
mit einer anderen Funktion, z.B. barplot()
auszuführen.Der Befehl tcpdump steht nun nicht nur auf
boa, sondern auch auf allen anderen Praktikumsrechnern zur
Verfügung.
Achtung: Mit Hilfe von tcpdump kann man
allen Netzwerkverkehr eines Rechners mitschneiden. Beachte
also, dass Deine Kommilitonen die Möglichkeit haben, Deine
Passwörter mitzuschneiden, wenn Du keine verschlüsselten
Verbindungen benutzt! Benutze im Zweifelsfall die
Praktikums-Rechner nicht für sensitive/private
Kommunikation.
Leider hat sich in Aufgabe 1 ein Fehler eingeschlichen, denn von Paketgrößen war in Aufgabe 3 des 1. Übungszettels nie die Rede. Es soll eine Regression vorgenommen werden zwischen der Dateigröße und dem Durchsatz.
Achtung, wichtig: Denke daran, dass es in Aufgabe 3 des ersten Blattes einmal lineare und logarithmische Skalierung gab. Denke daher darüber nach, wie man hier bei der "linearen" Regression sinnvollerweise vorgeht. (An welcher Stelle macht man den Logarithmus? Es gibt prinzipiell und völlig unabhängig, ob man es in R löst oder sonstwie, zwei Möglichkeiten!) Genau diese Frage wurde in der Vorlesung behandelt. Wenn Du Dir nicht sicher bist, gib einen kurzen erklärenden Text mit Deiner Lösung ab.
Falls Du Dir nicht ganz sicher bist, ob Dein Programm das komplexe Logfile vom ersten Blatt korrekt auswertet, kannst Du in /home/prak/daten/3.uebung/ jetzt ein einfaches Perl-Skript als Musterlösung herunterladen.
Achtung: In der ersten Aufgabe ist uns ein kleiner Tippfehler unterlaufen! Das Symbol für die Kovarianz ist sxy und nicht (wie auf dem Blatt angegeben) s2xy. Sprich, in der Formel muss sie noch quadriert werden.
Die "normale" Varianz von x hingegen ist in der Tat das Quadrat der Standardabweichung s und ist somit wie angegeben definiert als s2x; sie muss also nicht nochmals quadriert werden.
Achtung: In der ersten Aufgabe ist uns ein Tippfehler unterlaufen! Es sind auch die Ergebnisse aus (d) zu analysieren, so dass es heissen muss: "Diskutiere die Ergebnisse aus (a), (b), (c) und (d)..."
Achtung: In der Fussnote 5 ist uns ein Tippfehler unterlaufen! Die beiden R-Funktionen, auf die wir hier hinweisen sind: qqplot() und ppoints()
Die Zeiten sind in Sekunden, die Paketgrößen in Bytes.
aov()-Kram...Auf den Praktikumsrechnern befinden sich jetzt in /home/prak/doc/ Teile der Dokumentation von S-Plus, welches so ähnlich wie R zu bedienen ist. Sehr vieles davon ist auf R übertragbar.
Der in R aov() genannte Analysis of Variances-Test wird
allgemein oft als ANOVA bezeichnet. Einfach mal in Google oder Wikipedia
danach suchen.
Eine umfassende, dabei aber übersichtlich gehaltene Seite über verschiedene Verteilungen, wie sie definiert sind, was ihre typischen Anwendungsfälle sind, befindet sich unter http://www.statsoft.com/textbook/stdisfit.html.
Ein Konfidenzintervall für z.B. E(R) ist folgendermaßen definiert:
KI = [R= - δ(K,α), R= + δ(K,α)]
Dabei ist die halbe Weite des Konfidenzintervalles:
halbe Weite = δ(K,α) = Standardabweichung der R-i ⋅ tf(1-α/2)/√K
Hierbei ist tf(1-α/2) das 1-&alpha/2-Quantil
der t-Verteilung mit f Freiheitsgraden (engl. degree of freedom).
K ist die Anzahl der unabhängigen Wiederholungen, so dass dann
f=K-1 gilt.
Man behauptet damit, dass gilt:
P[R= - δ(K,α) ≤ E(R) ≤ R= + δ(K,α)] = 1-α .
Der E(R) ist hierbei der Erwartungswert, also quasi der Mittelwert bei einer unendlich großen Anzahl an (unabhängigen) Wiederholungen. Wir machen also eine Aussage, dass unser geschätztes R= vom Erwartungswert mit einer Wahrscheinlichkeit von bla nicht mehr als blubb abweicht.
Anmerkung: Aus HTML-technischen Gründen ist hier "R-quer" als R- und "R-quer-quer" als R= dargestellt und "Wurzel aus K" als √K.
R selbst hat anscheinend keine Funktion dafür. Es geht aber relativ einfach mit sowas wie...
my<-c(10,20,15); my_i<-c(2,3,4); mp<-barplot(my, ylim=c(0,max(my+my_i))); segments(mp,my-my_i,mp,my+my_i) segments(mp-0.05,my-my_i,mp+0.05,my-my_i) segments(mp-0.05,my+my_i,mp+0.05,my+my_i)