Sobald alles abgearbeitet ist, enthält TMPLIST eine Liste von Zahlen – je eine pro Datei, die zum aktuellen Benutzer gehören. Die zweite For-Schleife addiert die Zahlen von TMPLIST in TSUM. Diese Schleife weist die gleiche Struktur auf wie die obige. Als Variable agiert in diesem Fall N.
Die Bash bietet über das Konstrukt $(( Mathematischer Ausdruck )) eingebaute Ganzzahl-Arithmetik. Das Skript verwendet dieses Konstrukt zweimal. Eine Funktion namens to_gb (Listing 8) erledigt das Ausdrucken jeder Berichtszeile.
Listing 8
to_gb()
{
# arguments: user usage-in-KB
local MB D1 D2 USER # lokale Variablen
USER=$1
MB=$(( $2/1024 )) # konvertieren in MByte
D1=$(( $MB/1000 )) # Ausgabe ganzzahlig in GByte
D2=$(( $MB-($D1*1000) )) # Rest berechnen
# display abcd MB as: a.bcd GB
printf "%s\t%s\n" $USER $D1.${D2:0:1}
return
}
Die Bash setzt voraus, dass Sie Funktionen vor dem Einsatz definieren. Dazu bietet es sich an, Funktionen in einer externen Datei zu speichern und über den Punktbefehl in Skripte einzubinden. Im Beispiel aus Listing 7 liegt die Funktion in der Datei functions.bash.
Die Funktion to_gb() beginnt mit der Definition einiger lokaler Variablen. Damit ignoriert sie jegliche Bedeutung, die diese Namen im aufrufenden Skript eventuell haben könnten, und die lokalen Werte gelangen nicht in den übergeordneten Kontext zurück.
Der größte Teil der Funktion besteht aus arithmetischen Operationen. Die Bash unterstützt ausschließlich Ganzzahl-Arithmetik. Möchten Sie eine einigermaßen genaue Gesamtgröße in GByte anzeigen, müssen Sie dazu einen gängigen Trick nutzen: Sie entnehmen zuerst die Ganzzahlen, dann den Rest des GByte-Wertes und setzen die Ausgabe per Hand zusammen.
Haben Sie zum Beispiel 2987 MByte und dividieren dies durch 1024, wäre das gerundete Ergebnis 2 GByte. Um ein genaueres Ergebnis anzuzeigen, dividieren Sie stattdessen zuerst 2987 durch 1000 (D1=2), dann berechnen Sie 2987-(2*1000). Der Wert für D2 beträgt dann 987. Anschließend geben Sie die Variable D1, ein Komma und dann die erste Ziffer von D2 ein: Das Ergebnis lautet dann 2.9. So sähe eine beispielhafte Ausgabe des Skripts aus:
BENUTZER BELEGT in GB andrea 80.5 karsten 14.3 monika 0.3
Der Befehl printf ermöglicht eine formatierte Ausgabe. Er erfordert einen Format-String, gefolgt von Variablen, um den Ausdruck zu befüllen. Kennbuchstaben hinter Prozentzeichen geben an, wo die Variablen-Inhalte landen. Im Beispiel bestimmt %s die Stellen, an denen die Funktion die Werte einfügt. Hier gibt der Buchstabe s an, dass es sich um eine Zeichenkette handelt.
Die Zeichen \t und \n im Format-String entsprechen den Steuerzeichen Tabulator und Zeilenumbruch. Wollen Sie die Zeile explizit beenden, müssen Sie Letzteres angeben.
Das nächste Skript (Listing 9) berechnet Fakultäten und veranschaulicht eine andere Art von For-Schleife, die dem ähnelt, was in vielen Programmiersprachen üblich ist, wie zum Beispiel in C.
Listing 9
#!/bin/bash F=1 for (( I=$1 ; I>1 ; I-- )); do F=$(( $F*$I )) done echo $1'! = '$F exit 0
Die For-Syntax nutzt eine Schleifenvariable (I) zusammen mit einem Startwert ($1, also der erste Parameter, den Sie an das Skript übergeben), einer Bedingung zum Fortsetzen der Schleife sowie einem Ausdruck, der angibt, wie sich die Variable nach jedem Schleifendurchlauf ändert.
Die Schleife verarbeitet die Variable I. Am Ende jeder Iteration verringert das Skript den Wert von I um 1 (I++ würde ähnlich I um den Wert 1 erhöhen). Die Schleife läuft durch, solange I größer als 1 ist. Der Rumpf der Schleife multipliziert F (am Anfang auf 1 gesetzt) mit jedem nachfolgenden I. Das Skript endet mit der Ausgabe des Ergebnisses:
$ ./fact 6 6! = 720
Wie man hier sieht, lässt sich auch in der Shell recht zügig Mathematik betreiben. Probieren Sie zum Beweis einmal ./fact 10000.
Menüs erzeugen
Das letzte Skript demonstriert die eingebaute Fähigkeit der Bash zum Generieren von Menüs über den Select-Befehl (Listing 10).
Listing 10
#!/bin/bash
PATH=/bin:/usr/bin
PFILE=/usr/local/sbin/userpkgs # Format der Eingabe: pkgname menu_item
PKGS=( $(cat $PFILE | awk '{print $1}') ) # Array von Paketnamen
MENU="$(cat $PFILE | awk '{print $2}') Fertig" # Liste der Menüpunkte
select WHAT in $MENU; do
if [ $WHAT = "Fertig" ]; then exit; fi
I=$(( $REPLY-1 ))
PICKED=${PKGS[$I]}
echo Installiere Paket $PICKED ... Bitte haben Sie Geduld!... Befehle, um das Paket zu installieren ...
done

