Open Source im professionellen Einsatz
Linux-Magazin 05/2001

Shell-Scripting mit Scheme

Wechsel auf der Brücke

Scripting funktioniert nicht nur bei den üblichen Verdächtigen wie Bash, Korn-Shell und Python, sondern auch mit Scheme. Im Zentrum des Artikels stehen darum die Shell-Programmierung mit Scheme sowie die Programmierung fürs Internet.

933

Die Scheme-Shell Scsh (http://www-swiss.ai.mit.edu/ftpdir/scsh) wurde speziell für das Unix-Scripting entworfen; für die interaktive Benutzung ist sie in ihrer jetzigen Form bei weitem nicht so gut zu gebrauchen wie zum Beispiel die Bash oder Z-Shell. Es gibt weitere Implementierungen in Lisp-Sprachen. Für die hartgesottenen Emacs-Fans sei auf die Eshell verwiesen, eine Shell für Emacs in Emacs Lisp (http://www.emacs.org/~johnw/eshell.tar.gz).

Benutzer einer Debian-Installation können auf ein HDEB-Paket der Scheme-Shell zurückgreifen, Benutzer einer RPM-basierten Distribution müssen den Weg über die Quellen (ftp://ftp-swiss.ai.mit.edu/pub/su/scsh/scsh.tar.gz) einschlagen. Auch andere Scheme-Dialekte sind für das Scripting einsetzbar, die Scsh bietet jedoch die beste Integration in die Unix-Werkzeuge.

Warum soll man für die Shell-Programmierung auf ein Scheme ausweichen? Der Autor der Scheme-Shell, Olin Shivers, stellt dazu fest: "Unix-Shells sind echte Programmiersprachen. Sie besitzen Variablen [...]. Aber sie sind schreckliche Programmiersprachen. Die Datenstrukturen bestehen meist nur aus Integers und String-Vektoren. Die Möglichkeiten zur prozeduralen Abstraktion sind minimal bis nicht existent. Die lexikalischen und syntaktischen Strukturen sind mehrfach bestimmt, prinzipienlos und verschnörkelt." [1]

Die ziemlich harsche Kritik zielt hauptsächlich auf den Programmiersprachen-Aspekt. Außen vor bleiben auch die vielen Funktionen, die das Arbeiten auf der Kommandozeile so komfortabel machen. In diesem Bereich hat die Scsh ihre großen Schwächen. Dass die Shell-Programmierung keine ganz einfache Materie ist, kann man vielleicht an der Länge der Unix-FAQ [3] ermessen.

Umbenennung einer Reihe von Dateien

Die Frage nach der Umbenennung einer Reihe von Dateien findet man auch in Punkt 2.6 der Unix-FAQ. Es handelt sich also um ein nicht triviales Problem, sonst fände es sicherlich nicht seinen Weg in die FAQ. Hier eine Möglichkeit für eine Bourne Shell:

function rename_1 (){
  from=$1
  to=$2
  mv $from $(echo $to | tr `[A-Z]' `[a-z]').html
}
for f in *.HTM; do
  base=`basename $f .HTM`
  rename_1 $f $base
done

Wenden wir das Ganze einmal auf folgende vier Dateien an: T1.HTM, T2.HTM, with blank.HTM und T3.HTM. Es resultiert die Ausgabe: mv: Beim Verschieben mehrerer Dateien muss das letzte Argument ein Verzeichnis sein. Diese Fehlermeldung ist nicht sehr hilfreich. Schauen wir mal nach, wo denn etwas schief gegangen sein könnte. Ein ls zeigt an, dass die Umbenennungen für alle Dateien - bis auf jene mit Leerzeichen - geklappt haben.

Es handelt sich also um ein Problem von Leerzeichen in Dateinamen, den Hinweis auf ein Verzeichnis kann man wohl getrost vergessen. Versuchen wir es also einmal auf eine andere Art:

function rename_2 (){
  from=$1;
  to=$2
  mv $from "$(echo $to | tr `[A-Z]' `[a-z]').html"
}

Folgende Dateien sind da: t1.html, t2.html, with blank.html und t3.html. Der zweite Weg scheint brauchbar. Für Umlaute oder andere ungewöhnliche Namen in Dateinamen müssen Sie aber sehr viel über Quoting, Prozesssubstitution und Sonderzeichen wissen. Nun einmal das Ganze in der Scheme-Shell:

#!/usr/local/bin/scsh -l ./stringhax.scm -s 
!#
(define (rename-them)
  (let ((file-list (glob "*.HTM")))
    (for-each 
      (lambda(x) (rename-file x 
 (replace-extension 
          (downcase-string x) ".html")))
      file-list)))
(rename-them)

Auf die gleichen Dateien angewandt erhalten wir direkt die erwarteten Ergebnisse. Betrachten wir den Aufbau eines Scsh-Skripts: Wie bei jedem Skript wird in der ersten Zeile angegeben, durch welches Programm dieses Skript bearbeitet werden soll. Die nachfolgenden Zeilen sind Kommandozeilen-Argumente für die Scsh, aufgeführt sind sie in Kapitel 2 aus [2], Seite 161.

Im Beispiel wird zunächst die Datei stringhax.scm geladen, in der man einige Erweiterungen für die Behandlung von Zeichenketten findet; benötigt wird nur die Funktion downcase-string. Das -s begrenzt die erweiterte Kommandozeile und muss immer die letzte Option vor !# sein.

Im Folgenden wird eine Funktion rename-them definiert. glob pattern erzeugt eine Liste, deren Elemente pattern entsprechen. Daraufhin wird in einer Schleife jede Datei aus der Liste einzeln umbenannt. Das erfordert gleich mehrere Funktionen: Eine benennt die Dateien um, eine weitere ersetzt die Erweiterung und die dritte benennt die Dateinamen in Kleinbuchstaben um. Der Aufruf der gerade definierten Funktion beschließt das Skript.

Listing 1: Ausnahmebehandlung in der Scsh

(define (error-handling-test)
  (let ((dir "dir"))
    (create-directory "dir")
    (with-errno-handler
     ((e1 d1)
      ((errno/exist)
       (format #t "errno-msg = ~A~%
     syscall = ~A~%data = ~A~%~%
                   Directory exists~%"
               (nth d1 0) (nth d1 1) (nth d1 2)))
      (else (error "Do not know that to do now, giving upn")))
     (create-directory dir))
    (with-errno-handler
     ((e2 d2)
      ((errno/isdir) 
       (display "Ups, was a directory
                 so running delete-directory insteadn")
       (delete-directory dir)))
     (delete-file dir))))

Listing 2: Awk auf Scheme-Art

#!/usr/local/bin/scsh -s
!#
;;; Add the numbers of kb of free and used disk space for all the volumes
;;; reported by df(1)
(define (df-free+used)
  (let ((df-read (field-reader))) ;df 1
    (exec-epf 
     (| (df) ;df 2 
        (begin 
          (read-line) ; skip first line of df ;df 3
          (awk (df-read) (line fields) ;df 4
               ((used-kb 0) (free-kb 0)) ;df 5
               (#t  ;df 6
                 (values (+ used-kb (string->number (nth fields 2)))
                         (+ free-kb (string->number (nth fields 3)))))
               (after
                (values `(`used-mb ,(/ used-kb 1024.0)) ;df 7
                        `(`free-mb ,(/ free-kb 1024.0))))))))))
(receive 
 (used-list free-list) 
 (df-free+used) ; df 8
 (format #t "Es sind ~A MB belegt und noch ~A MB frei.~%"
         (cadr used-list)
         (cadr free-list)))

Das Umwandeln von Umlauten funktioniert aber auch in der Scheme-Shell nicht! In den Quellen zu diesem Artikel habe ich daher eine weitere Funktion definiert, die auch die Umlaute korrekt ersetzt [7].

Merkmale der Scheme-Shell

Vielleicht konnte Sie das Beispiel davon überzeugen, dass man mit einer vollwertigen Programmiersprache die Shell-Programmierung vereinfachen kann. Für die Verbindung mit dem zugrunde liegenden System bietet die Scsh

  • Mechanismen, um die Daten der Unix-Programme und der Shell zu integrieren, sowie
  • eine in Scsh umgesetzte Posix-API.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Wir können auch anders

    Bisher vorgestellte Programme waren in funktionaler Weise implementiert. Schemes Stärken liegen zwar hauptsächlich in diesem Bereich, jedoch gibt es auch die Möglichkeit, objektorientiert vorzugehen.

  • Standards? Standards!

    Der Scheme-Standard hat einen recht kleinen Umfang, also greifen Programmierer für größere Projekte zwangsläufig auf Erweiterungen zurück. Im Zentrum dieses Artikels stehen daher Standard-Scheme und seine Erweiterungen.

  • Funktioneller gehts nicht

    Nachdem im vorherigen Teil die Basiselemente der Scheme-Programmierung vorgestellt wurden, soll in diesem Artikel ein essentieller Vorteil von Scheme die Hauptrolle spielen, nämlich die funktionale Programmierung.

  • Chicken Scheme in Version 4.8.0

    Die freie Scheme-Implementierung Chicken ist in Version 4.8.0 für Linux, Windows und Mac OS X erhältlich.

  • Scheme-Implementierung Racket 3.5 bringt Submodule

    Die freie Scheme-Implementierung Racket (ehemals PLT Scheme) ist in Version 5.3 mit zahlreichen Neuerungen erhältlich.

comments powered by Disqus

Ausgabe 11/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.