Holm Sieber

Skriptsprachen (Teil 1)

Dieser Vortrag zeigt anhand ausgewählter Beispiele, wie umfangreich die Möglichkeiten von Shellprogrammen unter Linux sind. Im Besonderen werden in diesem ersten Teil reguläre Ausdrücke ausführlich behandelt und es wird ein Überblick über die vielen kleinen Tools gegeben, die soviel Arbeit abnehmen können.

Übersicht

  • -> 1 Reguläre Ausdrücke
  • 2 Beispiele zur Shellprogrammierung der bash
  • 3 Übersicht nützlicher Werkzeuge
  • 1 Reguläre Ausdrücke

    Die folgende Übersicht gibt alle wichtigen Metazeichen an, die in regulären Ausdrücken benutzt werden können.

    .
    Steht für ein beliebiges Zeichen.
    *
    Steht für ein beliebig häufiges Auftreten des Zeichens, das unmittelbar davor steht.
    [...]
    Steht für eines der in den eckigen Klammern eingeschlossenen Zeichen.
    \{n,m\}
    Steht für ein wiederholtes Auftreten eines einzelnen Zeichens, das unmittelbar davor steht.
    ^
    Setzt voraus, dass die folgende logische Bedingung am Zeilenanfang erfüllt ist.
    $
    Setzt voraus, dass die folgende logische Bedingung am Zeilenende erfüllt ist.
    \
    Die spezielle Bedeutung des folgenden Zeichens wird aufgehoben.
    \( \)
    Überträgt das zwischen \( und \) eingeschlossene Muster in einen speziellen Puffer. Bis zu neun Muster können auf diese Weise in einer Zeile gespeichert werden.
    \n
    Steht für das n-te Muster, das zuvor mit \( und \) gespeichert worden ist.

    Die Wirkungsweise der einzelnen Metazeichen soll mit den folgenden einfachen Beispielen etwas verdeutlichet werden.

    2 Beispiele zur Shellprogrammierung der bash

    Rechnen

    Die Bash ermöglicht arithmetische Berechnungen. Der Ausdruck in $[...] wird entsprechend den üblichen Regeln ausgewertet. Neben den ganzzahligen Grundrechenoperationen werden eine ganze Reihe von Bitoperationen und logischen Operationen unterstützt.

    echo $[5*3] # Multiplikation echo $[8%3] # 8 modulo 3 echo $[3<<2] # bitweises Verschieben echo $[7#14] # die Zahl 14 im 7-er System

    Das folgende Shellskript erwartet eine Zahl als Parameter. Es wird von 1 bis zu dieser Zahl gezählt, wobei jede Sekunde eine Zahl ausgegeben wird.

    #!/bin/sh if test $# -eq 0 then echo 'Syntax: zaehle <nr>' exit 1 fi i=1 while test $i -le $1 do echo $i i=$[$i+1] sleep 1 done

    Ausgabe von Programmen

    Die Ausgaben von Programmen können auf einfache Weise in einem Shellskript benutzt werden. Das zwischen `...` eingeschlossene Kommando wird an dieser Stelle ausgeführt, und die Ausgaben des Kommandos können im Skript benutzt werden.

    Das folgende Beispiel liest in einer Reihe von Postscriptdateien, wieviele Seiten sie enthalten, und zählt alle Seiten zusammen.

    #!/bin/sh n=0 for f in *.ps do echo -n "File \`$f': " i=`grep %%Pages: $f | sed -e 's/%%Pages: *//'` echo $i Seiten n=$[$n+$i] done echo "Seitenanzahl: $n"

    Fileumlenkung

    Die Bash bietet vielfältige Möglichkeiten die Ausgabe von Programmen umzulenken. Zwei besonders interessante Möglichkeiten sollen vorgestellt werden.

    1. Zusammenführen von stdout und stderr

    Viele Programme schreiben ihre Ausgaben auf stdout und stderr. Sollen beide Ströme in ein File gelenkt werden, ist wie folgt vorzugehen:

    programm > file_out 2>&1

    Der Ausdruck bedeutet, dass die Ausgaben von stderr auf stdout umgeleitet werden, die wiederum in das File file_out ausgegeben werden.

    2. Ausgabe auf stderr

    Manchmal besteht der Wunsch, aus einem Skript heraus Ausgaben nach stderr zu schreiben, um so eventuell die Ausgaben des Shellskriptes zu trennen. Mit echo und der Fileumlenkung ist das wie folgt möglich:

    echo "Hello World" 1>&2

    Die Ausgaben erscheinen auf stderr.

    Hier Dokumente

    Mit dem echo-Kommando und der Dateiumlenkung ist es möglich, aus einem Shellskript heraus eine neue Datei anzulegen:

    echo "Hello World!" > new_datei

    Sollen in die Datei fortlaufend mehrere Zeilen geschrieben werden, kann anstatt mehrerer echo-Zeilen folgende Lösung benutzt werden:

    cat > new_datei <<EOF Hallo Welt! Das ist ein mehrzeiliger Text, der in der neuen Datei erscheinen soll. EOF

    Input Seperator

    Folgendes Problem: Im Shellskript soll ein Textfile feldweise gelesen werden, wobei die Felder durch Tabulatoren getrennt sinden. Normalerweise liefern folgende Zeilen

    for i in `cat textfile` do echo $i done

    die Datei wortweise.

    Für die Trennung einer Zeile in einzelne Wörter benutzt die Bash die interne Variabel IFS, die alle möglichen Trennzeichen enthält. Standardmäßig ist hier IFS=<space><tab><newline> eingestellt.

    Das oben gestellte Problem wird nun durch folgende Zeilen gelöst:

    IFS="<tab>" for i in `cat textfile` do echo $i done

    Talking Clock

    Ein etwas umfangreicheres Beispiel für die Shellprogrammierung ist die Talking Clock. Das Skirpt beherrscht im Wesentlichen drei verschieden Arten von Uhren: eine sprechende Uhr, eine Kirchenuhr und eine Kuckucksuhr. Bei den ersten beiden wird die Zeit jede Viertelstunde angezeigt, indem unter Verwendung fertiger Sounddateien die Zeit angesagt wird bzw. entsprechend häufig die Uhr geschlagen wird. Die Kuckucksuhr zeigt zu jeder vollen Stunde die Zahl der Stunden an.

    Der Aufruf der Uhr erfolgt am einfachsten via crontab. Für die Nutzung der Uhr werden außerdem die folgenden Soundfiles benötigt.

    3 Übersicht nützlicher Werkzeuge

    Die folgende Übersicht stellt eine Reihe mehr oder weniger leistungsfähiger Programme vor, die beim Schreiben von Shellskripten von vielfältigem Nutzen sein können.

    awk
    einfache Scriptsprache
    basename
    Verzeichnis und Suffix von Dateinamen entfernen
    cat
    Dateien aneinanderhängen und auf stdout schreiben
    col
    Bestimmte Steuerzeichen herausfiltern
    colrm
    Spalten aus einer Datei entfernen
    cut
    Abschnitte von Zeilen einer Datei entfernen
    diff
    Vergleich zweier Textdateien
    dirname
    extrahiert Verzeichnisnamen aus einem Pfad
    echo
    Textzeile ausgeben
    expand
    Tabs zu Leerzeichen expandieren
    expr
    Ausdruck auswerten (berechnen)
    file
    Dateityp bestimmen
    find
    Dateien in einer Verzeichnishierarchie suchen
    fmt
    einfacher Textformatierer
    fold
    lange Zeilen umbrechen
    getopt
    Befehlsoptionen auswerten
    grep
    Zeilen ausgeben, die einem Suchmuster entsprechen
    head
    die ersten Zeilen einer Datei ausgeben
    id
    Benutzer- und Gruppen-Id ausgeben
    join
    Zeilen zweier Dateien ueber ein gemeinsames Feld zusammenfuegen
    kill
    Signale an Prozesse senden
    logname
    Benutzername ausgeben
    look
    Binaere Suche in einer sortierten Datei
    nohup
    Hintergrundprozess starten und von Terminal abkoppeln
    nl
    nummeriert die Zeilen in einer Datei
    paste
    Zeilen zweier Dateien mischen
    perl
    umfangreiche Scriptsprache, auch objektorientiert
    printf
    Daten formatieren und ausgeben
    rev
    Reihenfolge der Zeichen jeder Zeile einer Datei umdrehen
    sed
    Stream-Editor
    sleep
    eine bestimmte Zeit warten
    sort
    Zeilen von Textdateien sortieren
    tac
    Zeilen einer Datei in umgekehrter Reihenfolge ausgeben
    tail
    letzte Zeilen einer Datei ausgeben
    tee
    einen Eingabestrom auf zwei Ausgaben zugleich lenken
    test
    Dateitypen testen und Werte vergleichen
    tr
    Zeichen ersetzen oder löschen
    true
    tut nichts, immer erfolgreich (Rückkehrcode=0)
    false
    tut auch nichts, aber mit Fehler (Rückkehrcode=1)
    uname
    Systeminformationen ausgeben
    uniq
    entfernt doppelte Zeilen aus einer sortierten Datei
    wc
    Zeichen, Worte und Zeilen zählen
    xargs
    Befehlszeilen aus der Standardeingabe zusammenbauen