Linuxer gelten als tippfaul und effizienzliebend. Dafür gibt es viele Anwendungsgebiete. Da die Tastatur das wichtigste Eingabegerät neben der Maus ist, bietet sie sich herrvorragend als Betätigungsfeld an. Aus der Überlegunug heraus entstand das Neo-Keyboardlayout [1], das die Tasten ausgehend von den Erfahrungen mit dem Dvorak-Layout und einigen statistischen Überlegungen neu anordnet (siehe Abbildung 1).
Abbildung 1: Das Neo-Layout ordnet die Tasten komplett neu an. Es kennt insgesamt sechs Ebenen, um Zeichen zu erzeugen.
Neu im Vergleich zur klassischen Qwertz-Form ist, dass Neo insgesamt sechs Tastenebenen kennt statt nur zwei. Fans der Anordnung nehmen für sich in Anspruch, erheblich schneller tippen zu können. Vor neuen Schreibrekorden steht jedoch die Lern- und Umgewöhnungsphase. Hier hilft Das von Martin Engel verfasste Skript »xmodmap2tastenaufkleber.sh« [2] hilft, die einzelnen Tastenkombinationen von einer per »xmodmap -pke« erzeugten Belegung in Schaubilder umzusetzen (siehe Abbildung 2).
Abbildung 2: Wer beim Neo-Layout nicht den Überblick verlieren will, dem hilft die Tafel von »xmodmap2tastenaufkleber.sh«, die eine Tastaturbelegung in eine SVG-Datei umwandelt.
Wer jedoch das Skript unter die Lupe nimmt, reibt sich verwundert die Augen. Da verwendet der Autor gleich mehrfach den »cat«-Befehl, um eine Pipe mit notwendigem Input zu versorgen (siehe Listing 1).
01 [...]
02 #================================================
03 # Herausfiltern von Modifikatortasten, etc.
04 # Die zu filternden Tastencodes stehen in den runden
05 # Klammern jeweils durch ein Oder-Zeichen getrennt
06
07 cat tmp_$1 | grep -v -E "^(9|51|65|66|94|113|115|116)[^0-9]" > tmp_$1
|
Missverstanden
Das Beispiel demonstriert anschaulich, wieso »cat« vermutlich der am häufigsten von Shellprogrammierer missverstandene Befehl ist: Sein Name ist eine Unix-typische Verkürzung von "Concatenation", zu deutsch Zusammenfügen. Dazu gehören aber mindestens zwei, so sucht
cat *.report | sort | head -3
die drei lexikalisch ersten Einträge aus einer ganzen Sammlung von Berichten heraus. Aber selbst dieses Beispiel ist unnötig, denn viele der Basisbefehle verstehen mehr als ein einzelnes Argument, so auch »sort«: das kürzere
sort *.report | head -3
täte es auch. Das in Zeile 7 von Listing 1 verwendete »grep« kann selbst Eingabedateien öffnen, mit »grep -E [...] "tmp_$1"« erreichte der Autor prinzipiell das Gleiche. Weil er aber seine temporäre Datei nicht in Doublequotes kleidet, scheitert das Programm an Argumenten, die etwa Leerzeichen im Namen tragen [3]. Schwerwiegender ist allerdings, dass das Ergebnis der Pipe in derselben Zeile wieder in seine Eingabedatei schreibt. Das kann nicht verlässlich funktionieren. Sobald die Bash eine solche Kette interpretiert, öffnet sie die letzte angegebene Datei mit der Open-Optionen »O_TRUNC« und sägt sich damit praktisch selbst den Ast ab, auf dem sie sitzt.
Teure Prozesse
Nicht alle Kommandozeilentools beherrschen jedoch beliebig viele Dateiargumente - einige noch nicht einmal eine einzige Eingabedatei. Das Programm zum zeichenweisen Ersetzen, »tr«, ist so ein Beispiel, es akzeptiert seine Eingabe ausschließlich aus der Standardeingabe. Ist hier der Bash-Programmierer also auf »cat« angewiesen und muss einen wertvollen Prozess starten? Mitnichten, denn die Shell kennt dafür die Form
tr 'A-Z' 'N-ZA-M' < input.txt > output.txt
um beispielsweise ein Rot13 für Großbuchstaben zu implementieren. Wer den Inhalt einer Datei in einer Shellvariable braucht, darf das übrigens mit
indatei=input.txt
daten=$(<$indatei)
formulieren. Gerade in Schleifen sind immer neu gestartete Unterprozesse für jede Menge Ressourcenverbrauch verantwortlich. Ein kurzer Benchmark durchsuchte knapp 3 300 Dateien nach einem Suchstring. Die Variante in Listing 2 braucht daher 3 300 Prozesse mehr als die kürzere Variante in Listing 3. Das zweite Skript benötigte 88 Prozent mehr Laufzeit als das erste. Hängt man hinten an die Pipe ein weiteres, nutzloses »| cat« an, so dauert dies 153 Prozent länger als ein einzelnes »grep«. Zwei solche Aufrufe benötigen schon zusätzliche 239 Prozent und dreimal »cat« schlägt mit einer Zugabe von gesalzenen 322 Prozent zu Buche. Die letzteren Werte leiden überdurchschnittlich an den begrenzten Ressourcen auf dem Testrechner und lasten ihn vollständig aus. Dennoch zeigt das durchaus praxisnahe Beispiel, dass sich zusätzliche Prozesse erheblich im Schleifenrumpf auswirken.
01 #!/bin/bash
02 find $HOME/Artikel/2009/1* -type f |
03 while read i
04 do
05 cat "$i" | grep bashing > /dev/null
06 done
|
01 #!/bin/bash
02 find $HOME/Artikel/2009/1* -type f |
03 while read i
04 do
05 grep bashing "$i" > /dev/null
06 done
|