Zufallszahlen hinzugefgt

This commit is contained in:
rschaten 2002-04-12 11:55:28 +00:00
parent ff78ec65e4
commit 136b632f8f

View File

@ -336,3 +336,90 @@ esac
Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben. Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
\end{flushright} \end{flushright}
\index{trap=\texttt{trap}|)}\index{Signal|)} \index{trap=\texttt{trap}|)}\index{Signal|)}
\section{Chaoten: Dateien in zufällige Reihenfolge
bringen}\label{chaoten}\index{Zufallszahlen|(}
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses
Problem für uns eine Herausforderung darstellt\footnote{Denn schließlich hat
mpg123 schon von Hause aus eine Random-Funktion}, wollen wir vor dem Abspielen
der jeweiligen Datei etwas mit dem Dateinamen anstellen. Ob das eine einfache
Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf
einem externen Display angezeigt werden soll ist an dieser Stelle egal.
Das Problem ist, daß wir in der Shell nur über Umwege an Zufallszahlen kommen
können. Auf Systemen, in denen die Datei \texttt{/dev/urandom} existiert,
liefert uns der Kernel aber schon sehr zufällige Zeichenfolgen. Diese Folgen
können alle Zeichen enthalten, daher müssen sie vor der Benutzung für unsere
Zwecke noch etwas 'bereinigt' werden.
Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript:
\footnotesize
\index{!==\texttt{!=}}
\begin{listing}[2]{1}
#!/bin/sh
for i in `find $1 -type f -name "*.[mM][pP]3"`; do
\end{listing}
\normalsize
\begin{flushright}
Hier beginnt eine Schleife, die über alle Ausgaben des \texttt{find}-Kommandos
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type
f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
ignorieren Groß- / Kleinschreibung).
\end{flushright}
\footnotesize
\index{find=\texttt{find}}
\begin{listingcont}
echo `tr -dc "[:alpha:]" < /dev/urandom | \
dd count=8 bs=1 2> /dev/null`$i
\end{listingcont}
\normalsize
\begin{flushright}
Hier ist der 'magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe
ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enthält ein
\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus
einem Datenstrom entfernt. Die Daten erhält \texttt{tr} durch die
\texttt{<}-Umleitung aus oben genannter Datei.
Diese Datei liefert 'ohne Ende' Zeichen. Wir wollen aber nur acht Zeichen
haben, die wir unserem Dateinamen voranstellen können. Dazu benutzen wir das
Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung
von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach
\texttt{/dev/null} um.
\index{tr=\texttt{tr}}\index{dd=\texttt{dd}}
\end{flushright}
\footnotesize
\index{find=\texttt{find}}
\begin{listingcont}
done | sort | cut -b 9- | while read i; do
\end{listingcont}
\normalsize
\begin{flushright}
Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen
jeweils acht zufällige Zeichen vorangestellt wurden. Die Reihenfolge entspricht
allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem
Durchlauf gleich sein.
Um das zu ändern, pipen wir die Ausgabe der Schleife durch ein \texttt{sort}.
Da die ersten acht Zeichen jeder Zeile zufällig sind, erhalten wir so eine
zufällige Reihenfolge der Zeilen. Jetzt müssen wir nur noch durch ein
\texttt{cut} die zufälligen Zeichen abschneiden, und erhalten so die
ursprüngliche Liste von Dateien in einer zufälligen Reihenfolge.
Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der
\texttt{while}-Schleife können wir alle erforderlichen Sachen mit dem
Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben.
\index{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}}
\end{flushright}
\footnotesize
\index{find=\texttt{find}}
\begin{listingcont}
echo "Jetzt wird $i gespielt"
mpg123 "$i"
done
\end{listingcont}
\normalsize
\index{Zufallszahlen|)}