Störenfried Grafikterminal

Vielleicht kennt Ihr das Spiel. Man schlägt mit verbundenen Augen ein Lexikon oder Wörterbuch auf, und piekst mit einer Nadel oder einer Bleistiftspitze auf ein Wort. Das wiederholt man und muss dann aus den zufällig gewählten Worten eine Geschichte bilden oder einen Satz. Das kann ein Partyspass sein oder ein Trick, die eigene Kreativität anzuregen.

Statt sich mühsam die Augen zu verbinden und beim Gestocher zwischen den Wörtern mühsam zu entscheiden, welchem Wort die Stiftspitze nun näher war ist ein handlicher Rechner mit Shellscript viel handlicher, vorzugsweise ein Linuxrechner mit lustigen Pinguinaufklebern, OSX soll angeblich auch gehen, notfalls sogar Ballmerware für die es Native Win32 ports of some GNU utilities gratis und quelloffen gibt, ein unschätzbares Sammelsurium nützlicher Programme, von  cat über grep zu sed und wc. Ich habe vor ab und zu das ein oder andere kurz vorzustellen, und zum Experimentieren anzuregen.

Hier unten sehen wir eine Unsitte von Programmierern, nämlich ein ganzes, kleines Programm in eine Zeile zu quetschen:

<cite>

dat=/usr/share/hunspell/de_DE.dic; wcl=$(wc -l $dat); for dummy in foo bar; do z=$((RANDOM*RANDOM%${wcl/ */})); sed -n ${z}p $dat; done

</cite>

Störenfried/EPSTm

Graphikterminal/Sm

Hier arbeiten 3 Programme zusammen, nämlich bash, sed und wc. Bash startet automatisch als Hauptprogramm wenn Sie ein Terminal, bzw. xTerminal, xfterm4 oder wie es bei Ihnen heißt, eine Console oder eben bash öffnen. Bei den Gnu-Utils ist es sh.exe.

Das ist ein Interpreter, der Befehle entgegennimmt und schrittweise ausführt, wobei ein Schritt eine Zeile ist – man drückt Enter, und der Befehl wird exekutiert. Ausnahme ist, dass man die Zeilenschaltung maskiert, was ich jetzt nicht behandeln will, so dass man mehrere Zeilen eingibt aber die Ausführung aufschiebt, oder dass man mehrere Befehle in eine Zeile packt wie oben, und durch Semikolon trennt.

Aufgeteilt in einzelne Befehle haben wir hier 7 Zeilen:

<code>

dat=/usr/share/hunspell/de_DE.dic
wcl=$(wc -l $dat)
for dummy in foo bar
do
z=$((RANDOM*RANDOM%${wcl/ */}))
sed -n ${z}p $dat
done

</code>

In Zeile 1 wird die Wörterbuchdatei der Variable dat zugewiesen. Da kommen je nach installierten Programmen mehrere in Frage. So hat OpenOffice bzw. LibreOffice seine eigene, Firefox eine andere. Alle die ein Wort pro Zeile auflisten kommen in Frage. Ich benutze eine Variable, da ich 2x auf das Wörterbuch zugreife. Sollte ich das Wörterbuch ändern wollen muss ich es nur an der Stelle, an der ich es der Variablen zuweise ändern.

wcl=$(wc -l $dat) weist der Variablen wcl die Ausgabe des Kommandos wc zu, bzw. des Kommandos, welches in Klammern nach dem Dollarzeichen in runde Klammern eingekapselt ist. Die Zuweisung scheitert, wenn man vor oder hinter dem Gleichheitszeichen eine Leerstelle lässt.

Das Kommando selbst ist wc -l $dat, wobei dat die Wörterbuchdatei referenziert. wc ist ein Programm zum Wörterzählen (word count) -l ist ein Parameter, der hier dem Programm sagt, dass es Zeilen (lines) zählen soll, und $dat nennt man das Argument oder auch Paramater. Das Programm wc kann Wörter, Zeichen und Zeilen zählen. Mehr Details erfährt man mit wc –help, mit man wc oder mit info wc in aufsteigender Ausführlichkeit.

Die Ausgabe des Programms wäre 72374 de_DE.dic, sprich, die Datei hat rd. 70.000 Einträge. Wir sehen die Ausgabe aber nicht, weil wir die Ausgabe mit x=$(…) einer Variablen zuweisen. Leider kann man die Ausgabe des Dateinamens nicht unterdrücken, so dass wir diesen später herausoperieren müssen.

Dann folgt eine for-Schleife, die die Form for SOMETHING; do BLOCK_OF_SONSTWAS; done hat, und something steuert wie oft etwas geschieht während das, was geschieht, zwischen do und done steht. Das kann ein simpler Befehl sein oder eine Vielzahl Befehl, auch verschachtelte, neue Schleifen kommen in Betracht – für uns aber hier nicht.

Der Name dummy soll schon andeuten, dass wir die Variable, um die es sich handelt, gar nicht benötigen, ebenso wie foo und bar, die nur dafür sorgen, dass die Schleife 2x durchlaufen wird. Einmal ist die Variable dummy=foo, das andere Mal bar, aber das interessiert hier nicht.

Der Befehl z=$((RANDOM*RANDOM%${wcl/ */})) hat es ein wenig in sich. Es ist wieder eine Zuweisung, jetzt zur Variablen z, die den Wert dessen bekommt, was da rechts des Gleichheitszeichens steht. $((…)) ist ein Befehl an die Bash zu rechnen. In den Klammern steht einfach ein mathematischer Ausdruck, und der lautet a*a%b, sprich a mal a modulo b. Modulo ist der Rest der Division, also 7 modulo 3 ist 1, denn 7/3=2 Rest 1. Links des Modulos steht RANDOM zum Quadrat, und rechts steht wieder was Komplizierteres. RANDOM liefert bei jedem Aufruf eine Zufallszahl von 0 bis 32767. Ich will den x-ten Eintrag des Wörterbuchs herauspicken, und dies ist ja rund 70.000 Zeilen lang – also reicht eine einfache Zufallszahl bis 32.000 nicht aus. Deswegen die Multiplikation.

In wcl steht der Wert von oben, den wc -l ermittelt hat. Der Dateiname stört darin, und mit ${wert/muster/ersetzung} kann man im Wort wert das Muster muster durch den Text ersetzung ersetzen. Wert ist unsere Variable wcl die hier nicht mit $wcl angesprochen werden muss. Das Muster, nach dem ich suche, ist das Leerzeichen als Trenner zwischen der Zahl der Zeilen und dem Dateinamen. Der Stern fungiert als Jokerzeichen für beliebige weitere Zeichen (inkl. null). Ersetzt werden soll das Muster mit Nichts, das heißt wir schneiden es einfach ab. ${wcl/ */} macht also aus 72374 de_DE.dic  72374. Die Modulooperation liefert uns also eine Zeilennumer von 0 bis 72374 und speichert sie in der Variablen z zwischen.

Jetzt kommt noch das mächtige Programm sed zum Zuge. Mit sed -n ${z}p $dat rufen wir es auf. Wir übergeben 3 Parameter die durch Whitespace voneinander getrennt sind, das -n, das ${z}p und mit $dat nochmal den oben zugeordneten Dateinamen. Sed steht nicht für die Sozialistische Einheitspartei Deutschlands sondern für Stream EDitor. Man leitet in diesen Editor einen Text oder eine Textdatei hinein, und übergibt ein oder mehrere Kommandos die Zeilenweise auf den Eingabestrom angewendet werden. Der Schalter -n besagt, dass nichts ausgegeben werden soll (außer…). $z ist das soeben definierte z, also die Zufallszeilenzahl, aber da der Befehl dafür p ist wie print packen wir das z in geschweifte Klammern – sonst sucht die Bash nach $zp als einer Variablen namens zp. sed -n 123p $dat würde Zeile 123 drucken, sprich, auf den Bildschirm ausgeben. In den 60ern waren es wirklich Druckerähnliche Geräte, bzw. Teletypes, also Fernschreiber, von denen die Konsolen mit tty immer noch ihr Kürzel im System haben.

Das done besagt nun nicht, dass alles getan ist, sondern dass es in der Schleife hier zurückgeht, wenn der Schleifenkopf nicht was anderes sagt. Mit for dummy in {0..999} hätten wir auch 1000 Zeilen ausgeben können aber wir wollen nur 2 – oder wollen Sie 3?

Ergebnis meines Programms war

Störenfried/EPSTm
Graphikterminal/Sm

wobei die Kürzel hinter dem Slash irgendwas bedeuten müssen – das m wohl maskulinum, das S vielleicht Substantiv, aber EP_T?

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.