

	\documentclass[a4paper,11pt]{article}
	\usepackage{ngerman}
	\usepackage[latin1]{inputenc}
	\setlength\parskip{\medskipamount}
	\setlength\parindent{0pt}
	\begin{document}

	
 % Shellprogrammierung
 % Copyright Ronald Schaten
 % Lizenz: GFDL
 % 
 % $Name: $
 % $Revision: 1.1.2.17 $
 % $Source: /cvsroot/selflinux/tutorial/advanced/shellprogrammierung/shellprogrammierung,v $
 % SelfLinux-0.7.2
 %
 % Diese Datei ist Teil von SelfLinux http://www.selflinux.de
 %
 %%% $Id: shellprogrammierung,v 1.1.2.17 2002/12/21 19:35:35 fboerner Exp $

	\title{Shellprogrammierung}


	
	    \author{Ronald Schaten}
	    %\url{mailto:kahless@bigfoot.de}
    

	\maketitle

	
	
	%\ref{../index.tex}
	
		%\ref{programmierung.tex}
		Programmierung
	\ref{Shellprogrammierung}

    \par{Layout}
    Johannes Kolb
	    %\url{mailto:johannes.kolb@web.de}
    Matthias Kleine
	    %\url{mailto:kleine_matthias@gmx.de}
    Matthias Hagedorn
	    %\url{mailto:herbert-kw@t-online.de}
    
    	\par{Lizenz}
	GFDL
 
	\tableofcontents{}

        
	\section{Was ist die Shell?} \label{d73e69}
        
   
   
  \par
  
Die Shell ist ein Programm, mit dessen Hilfe das System die Benutzerbefehle
verstehen kann. Aus diesem Grund wird die Shell auch oft als Befehls- oder
Kommandointerpreter bezeichnet.
   
   \subsection{Sinn und Zweck} \label{d73e77}
        
    
    
  \par
  
In einem klassischen Unix-System (ohne die grafische Oberfläche X) greifen
die Benutzer über Terminals auf das System zu. Auf diesen Terminals können
nur Textzeichen dargestellt werden. Um dem Benutzer die Arbeit mit dem
System effektiv möglich zu machen, gibt es die Shell. Die Shell wird dabei
für drei Hauptaufgaben benutzt:
    

    \begin{list}{*}{}
     
	\item 
Interaktive Anwendung (Dialog)
     
     
	\item 
Anwendungsspezifische Anpassung des Unix-Systemverhaltens 
(Belegen von Umgebungsvariablen)
     
     
	\item 
Programmierung (Shell-Skripting). Zu diesem Zweck stehen einige
Mechanismen zur Verfügung, die aus Hochsprachen bekannt sind 
(Variablen, Datenströme, Funktionen usw.).
     
    \end{list}

    
  \par
  
Ursprünglich handelte es sich dabei um ein relativ einfaches Programm, der
Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist
praktisch die {\bf Mutter aller Shells}. Aus dieser entwickelten sich 

im Laufe der Zeit mehrere
Varianten, die alle ihre eigenen Vor- und Nachteile mit sich bringen. Da es
unter Unix kein Problem darstellt den Kommandointerpreter auszutauschen,
stehen auf den meisten Systemen mehrere dieser Shells zur Verfügung. Welche
Variante ein Benutzer verwenden möchte ist reine Geschmackssache.
    
   

   \subsection{Die Qual der Wahl} \label{d73e104}
        
    
    
  \par
  
Um die Auswahl einer Shell zu erleichtern, werden hier die wichtigsten
Varianten kurz vorgestellt. Sie sind aufgeteilt in Einfach- und 
Komfort-Shells. Die Komfort-Shells zeichnen sich durch komfortablere 
Funktionen zur interaktiven Bedienung aus, während die Einfach-Versionen 
üblicherweise für die Programmierung benutzt werden.
    
    
  \par
  
	 {\bf Einfach-Shells:}
    
    \begin{list}{*}{}
     
	\item 
Die {\bf Bourne}- oder 
{\bf Standard-Shell}
({\bf sh}) ist die kompakteste und einfachste 
Form. Sie bietet schon Mechanismen wie die Umlenkung der Ein- oder 
Ausgaben, Wildcards zur Abkürzung von Dateinamen, Shell-Variablen und 
einen Satz interner Befehle zum Schreiben von Shell-Prozeduren. 
Neuere Versionen beherrschen auch das Job-Controlling. Für die
Entwicklung von Shell-Skripten sollte man sich auf diese Shell
beschränken, da sie auf praktisch allen Systemen zur Verfügung steht.
So bleiben die Skripte portabel.
     
     
	\item 
Die {\bf Korn-Shell} ({\bf ksh}),
eine Weiterentwicklung der {\bf Bourne-Shell}, erlaubt
das Editieren in der Befehlszeile. Außerdem gibt es hier
History-Funktionen um auf zurückliegende Befehle zurückgreifen zu können,
eine Ganzzahl-Arithmetik, verbesserte Möglichkeiten zur Mustererkennung,
Aliase und das Job-Controlling.
Ein Alias ist dabei eine Abkürzung für einen Befehl. Beispielsweise kann 
man das häufig benutzte {\bf ls -la} einfach durch 
{\bf la} ersetzen. 
Unter Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe 
der Benutzer die Ausführung von Prozessen selektiv stoppen oder fortsetzen 
kann.
     
     
	\item 
Die {\bf C-Shell} ({\bf csh})
bietet ähnliche Annehmlichkeiten wie die 
{\bf Korn-Shell},
lehnt sich aber in der Syntax sehr stark an die Programmiersprache C
an. Sie sollte nach Möglichkeit nicht zur Shell-Programmierung benutzt
werden, da sie an vielen Stellen nicht so reagiert, wie man es erwarten
sollte.
     
    \end{list}
    
  \par
  
	 {\bf Komfort-Shells:}
    
    \begin{list}{*}{}
     
	\item 
Die {\bf Bourne-Again-Shell} ({\bf bash}) 
ist voll abwärtskompatibel zur {\bf sh}, bietet
aber von allen Shells die komfortabelsten Funktionen für das interaktive
Arbeiten. Da die Bash ein GNU-Produkt ist, ist sie die Standard-Shell
auf allen Linux-Systemen. Sie steht aber auch auf den meisten anderen
Unixen zur Verfügung.
     
     
	\item 
Die {\bf T-C-Shell}({\bf tcsh})
verhält sich zur {\bf C-Shell} wie die 
{\bf Bourne-Again-Shell} zur Standard-Shell. Sie ist 
voll kompatibel, bietet 
aber zusätzliche Komfort-Funktionen.
     
     
	\item 
Die {\bf Stand-Alone-Shell} ({\bf sash}) 
ist vor allem nützlich für die
{\bf System-Recovery}. Sie kann gegen statische Bibliotheken gelinkt
werden und beinhaltet bereits (teilweise vereinfachte) Formen von
Standard-Systemkommandos. Kann man also, nach einem System-Crash,
eine statisch gelinkte sash erreichen, ist es oft möglich, mit
ihrer Hilfe das System wiederherzustellen. Nähere Informationen
finden sich auf 
http://www.canb.auug.org.au/\~{}dbell/ und 

http://www.baiti.net/sash/.
     
    \end{list}
   
  \section{Wofür Shell-Programmierung?} \label{d73e234}
        
   
   
  \par
  
Shell-Skripte werden im Wesentlichen aus zwei Gründen geschrieben: Erstens,
weil man so ständig wiederkehrende Kommandos zusammenfassen kann, die
dann mit einem einfachen Aufruf starten, und zweitens, weil man
so einfache Programme schreiben kann, die relativ intelligent Aufgaben 
erledigen können.
   
   
  \par
  
Der erste Aspekt ist wichtig, wenn man beispielsweise regelmäßig 
auftretende Aufgaben erledigen möchte, wie z. B. das Backup von Log-Dateien.
In dem Fall schreibt man sich ein Skript, das die Dateien archiviert, und
sorgt dafür, dass dieses Skript in regelmäßigen Abständen aufgerufen wird
(per Cron-Job).
   
   
  \par
  
Der zweite Fall tritt ein, wenn man eine mehr oder weniger komplexe Abfolge 
von Befehlen ausführen möchte, die voneinander abhängen. Ein Skript,
das zum Beispiel eine Audio-CD kopieren soll, muss das 
Brennprogramm nur dann aufrufen, wenn der Einlesevorgang erfolgreich 
abgeschlossen wurde.
   
  \section{Wie sieht ein Shell-Skript aus?} \label{d73e255}
        
   
   
  \par
  
Wie schon erwähnt, kann ein Shell-Skript beinahe alles, was eine richtige
Programmiersprache kann. Dazu stehen mehrere Mechanismen zur Verfügung.
Um den Umfang dieses Dokuments nicht zu sprengen, werden an dieser Stelle
nur die wichtigsten vorgestellt.
   

   \subsection{Grundsätzliches} \label{d73e263}
        
    
    
  \par
  
Zunächst soll die Frage geklärt werden, wie man überhaupt ein ausführbares
Shell-Skript schreibt. Dabei wird vorausgesetzt, dass dem Benutzer der
Umgang mit mindestens einem Texteditor (vi, emacs 
etc.) bekannt ist.
    
    \subsubsection{HowTo} \label{d73e277}
        
     
     
  \par
  
Zunächst muss mit Hilfe des Editors eine Textdatei angelegt werden, in die
der {\bf Quelltext} geschrieben wird. Wie der aussieht, kann man 
anhand der
folgenden Abschnitte und der Beispiele im Anhang erkennen. Beim
Schreiben sollte man nicht mit Kommentaren geizen, da ein Shell-Skript
auch schon mal sehr unleserlich werden kann.
     
     
  \par
   
Die Datei ist unter geeignetem Namen zu speichern. 
Bitte hierfür nicht den Namen {\bf test} verwenden. Es existiert ein 
Unix-Systemkommando mit diesem Namen. Dieses steht fast immer eher im Pfad, 
d. h. beim Kommando {\bf test} würde nicht das eigene Skript 
ausgeführt, sondern 
das Systemkommando. Dies ist einer der häufigsten und zugleich einer der 
verwirrendsten Anfängerfehler. Mehr zu dem {\bf test}-Kommando 
unter
3.14 
     
     
  \par
  
Danach muss sie ausführbar gemacht werden. Das geht mit dem
Unix-Kommando {\bf chmod}.
     
     
  \par
  
Rechte werden unter Unix getrennt für den Benutzer ({\bf user},
{\bf u}), die Gruppe 
({\bf group}, {\bf g}) oder Andere 
({\bf others}, {\bf o}) vergeben. 
Außerdem kann man die Rechte für Gruppen zusammen ({\bf all}, 
{\bf a}) setzen. 
Man kann getrennt die Rechte für das Lesen ({\bf read}, 
{\bf r}), das Schreiben 
({\bf write, w}) und die Ausführung ({\bf execution, 
x}) einstellen. Um die Rechte zu 
setzen, muss man {\bf chmod} in Parametern mitgeben, auf wen sich 
das 
Kommando bezieht, ob das Recht gesetzt ({\bf +}) oder weggenommen 
({\bf -}) werden soll, 
und welche Rechte gemeint sind. Damit alle Benutzer das Skript ausführen 
dürfen, benutzt man das Kommando {\bf chmod ugo+x name}
oder einfach {\bf chmod +x name}. Mit 
{\bf chmod u+x name} hat nur der Besitzer der Datei 
Ausführungsrechte.
     
     
  \par
  
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgründen
auf den meisten Systemen das aktuelle Verzeichnis nicht im Pfad des
Benutzers befindet, muss man der Shell mitteilen, wo sie zu suchen hat: 
Mit {\bf ./name} wird versucht, im aktuellen Verzeichnis 
({\bf ./}) ein Programm namens
name auszuführen.
     
     
  \par
  
Auf den meisten Systemen befindet sich im Pfad der Eintrag 
{\bf \~{}/bin} bzw.
Bedingungen 
([]){\bf /home/benutzername/bin},
das bedeutet, dass man Skripte, die immer wieder
benutzt werden sollen, dort ablegen kann, so dass sie auch ohne eine 
Pfadangabe gefunden werden. Wie der Pfad genau aussieht kann man an der Shell
durch Eingabe von {\bf echo \$PATH} herausfinden.
     
    
    \subsubsection{Rückgabewerte} \label{d73e390}
        
     
     
  \par
  
Wenn unter Unix ein Prozeß beendet wird, gibt er einen Rückgabewert (auch
Exit-Code oder Exit-Status genannt) an seinen aufrufenden Prozeß zurück.
So kann der Mutterprozeß kontrollieren, ob die Ausführung des
Tochterprozesses ohne Fehler beendet wurde. In einigen Fällen (z. B. 
{\bf grep}) werden unterschiedliche Exit-Codes für 
unterschiedliche Ereignisse benutzt.
     
     
  \par
  
Dieser Rückgabewert wird bei der interaktiven Benutzung der Shell nur
selten benutzt. Aber in der Programmierung von Shell-Skripten ist er von
unschätzbarem Wert. So kann das Skript automatisch entscheiden, ob
bestimmte Aktionen ausgeführt werden sollen, die von anderen Aktionen
abhängen. Beispiele dazu sieht man bei der Beschreibung der Kommandos
{\bf if} (3.15),
{\bf case} (3.16), 
{\bf while} (3.18) und 
{\bf until}
(3.19), sowie in dem Abschnitt über
Befehlsformen (3.23).
     
     
  \par
  
In der {\bf Bourne-Shell} wird der Exit-Code des letzten 

aufgerufenen Programms
in der Variable {\bf \$?} abgelegt. Üblicherweise geben Programme 
den
Wert {\bf 0} zurück, bei irgendwelchen Problemen einen von 
{\bf 0} verschiedenen Wert.
Das wird im folgenden Beispiel deutlich:
     
     
      \begin{tt} \begin{scriptsize} user@linux / \$ 
cp datei /tmp
       \end{scriptsize} \end{tt} \linebreak 
      \begin{tt} \begin{scriptsize} user@linux / \$ 
echo \$?
       \end{scriptsize} \end{tt} \linebreak 
      \begin{tt} \begin{scriptsize} 0\end{scriptsize} \end{tt} \linebreak
      \begin{tt} \begin{scriptsize}  \linebreak user@linux / \$ 
cp datie /tmp
       \end{scriptsize} \end{tt} \linebreak 
      \begin{tt} \begin{scriptsize} cp: datie: Datei oder Verzeichnis nicht gefunden\end{scriptsize} \end{tt} \linebreak
      \begin{tt} \begin{scriptsize}  \linebreak user@linux / \$ 
echo \$?
       \end{scriptsize} \end{tt} \linebreak 
      \begin{tt} \begin{scriptsize} 1\end{scriptsize} \end{tt} \linebreak
     
     
  \par
  
Normalerweise wird man den Exit-Code nicht in dieser Form abfragen.
Sinnvoller ist folgendes Beispiel, in dem eine Datei erst gedruckt, und
dann - falls der Ausdruck erfolgreich war - gelöscht wird:
     
     
      \begin{tt} \begin{scriptsize} user@linux / \$ 
lpr datei \&\& rm datei
       \end{scriptsize} \end{tt} \linebreak 
     
     
  \par
  
Näheres zur Verknüpfung von Aufrufen steht im Kapitel über
Befehlsformen (3.23). Beispiele zur Benutzung 
von Rückgabewerten in 
Schleifen finden sich im Anhang unter A.1.
     
     
  \par
  
Auch Shell-Skripte können einen Rückgabewert an aufrufende Prozesse
zurückgeben. Wie das geht, steht in dem Abschnitt zu exit (3.22).
     
    
   
   
   \subsection{Variablen} \label{d73e497}
        
    
    
  \par
  
In einem Shell-Skript hat man - genau wie bei der interaktiven Nutzung der
Shell - Möglichkeiten, über Variablen zu verfügen. Anders als in den meisten
modernen Programmiersprachen gibt es aber keine Datentypen wie Ganzzahlen,
Fließkommazahlen oder Strings. Alle Variablen werden als String gespeichert.
Wenn die Variable die Funktion einer Zahl übernehmen soll, dann muss
das verarbeitende Programm die Variable entsprechend interpretieren.
(Für arithmetische Operationen steht das Programm expr zur Verfügung, 
siehe Zählschleifen-Beispiel unter 3.18)
    
    
  \par
  
Man muss bei der Benutzung von Variablen sehr aufpassen, wann die
Variable expandiert wird und wann nicht. (Mit Expansion ist das Ersetzen 
des Variablennamens durch den Inhalt gemeint). Grundsätzlich werden Variablen
während der Ausführung des Skriptes immer an den Stellen ersetzt, an denen
sie stehen. Das passiert in jeder Zeile, unmittelbar bevor sie ausgeführt 
wird.  Es ist also auch möglich, in einer Variable einen Shell-Befehl 
abzulegen. Im Folgenden kann dann der Variablenname an der Stelle des 
Befehls stehen.  Um die Expansion einer Variable zu verhindern, benutzt 
	 man das Quoting (siehe unter 3.5).
    
    
  \par
  
Wie aus diversen Beispielen hervorgeht, belegt man eine Variable, indem
man dem Namen mit dem Gleichheitszeichen einen Wert zuweist. Dabei darf
zwischen dem Namen und dem Gleichheitszeichen {\bf keine} Leerstelle 
stehen,
ansonsten erkennt die Shell den Variablennamen nicht als solchen und
versucht, ein gleichnamiges Kommando auszuführen - was meistens durch eine
Fehlermeldung quittiert wird.
    
    
  \par
  
Wenn man auf den Inhalt einer Variablen zugreifen möchte, leitet man
den Variablennamen durch ein {\bf \$}-Zeichen ein. Alles was mit 
einem {\bf \$} anfängt
wird von der Shell als Variable angesehen und entsprechend behandelt 
(expandiert).
    
   

   \subsection{Vordefinierte Variablen} \label{d73e530}
        	
    
    
  \par
  
Es gibt eine Reihe von vordefinierten Variablen, deren Benutzung ein 
wesentlicher Bestandteil des Shell-Programmierens ist.
Die wichtigsten eingebauten Shell-Variablen sind:
    
	
    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Aufrufparameter mit der Nummer n, n \verb+<+= 9
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Alle Aufrufparameter
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$@}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Alle Aufrufparameter
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$\#}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Anzahl der Aufrufparameter
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$?}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Rückgabewert des letzten Kommandos
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$\$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Prozeßnummer der aktiven Shell
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$!}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Prozeßnummer des letzten Hintergrundprozesses
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ERRNO}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Fehlernummer des letzten fehlgeschlagenen Systemaufrufs
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf PWD}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Aktuelles Verzeichnis (wird durch {\bf cd} gesetzt)
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf OLDPWD}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Vorheriges Verzeichnis (wird durch {\bf cd} gesetzt)
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
	
   
   
   \subsection{Variablen-Substitution} \label{d73e648}
        
    
    
  \par
  
Unter Variablen-Substitution versteht man verschiedene Methoden um die
Inhalte von Variablen zu benutzen. Das umfaßt sowohl die einfache Zuweisung
eines Wertes an eine Variable als auch einfache Möglichkeiten zur
Fallunterscheidung. In den fortgeschritteneren Shell-Versionen 
({\bf bash}, {\bf ksh})existieren sogar 
Möglichkeiten, auf Substrings von Variableninhalten 
zuzugreifen. In der Standard-Shell benutzt man für solche Zwecke 
üblicherweise den Stream-Editor {\bf sed}. Einleitende 
Informationen dazu finden sich im Kapitel über die Mustererkennung (3.7).
    
    
  \par
  
Die folgenden Mechanismen stehen in der Standard-Shell bereit, um mit
Variablen zu hantieren. Bei allen Angaben ist der Doppelpunkt optional.
Wenn er aber angegeben wird, muss die Variable einen Wert enthalten.
    
	
    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Variable = Wert}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Setzt die Variable auf den Wert.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \${Variable}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Nutzt den Wert von Variable. Die Klammern müssen nicht mit 
angegeben werden, wenn die Variable von Trennzeichen umgeben 
ist.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \${Variable:-Wert}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Nutzt den Wert von Variable. Falls die Variable nicht 
gesetzt ist, wird der Wert benutzt.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \${Variable:=Wert}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Nutzt den Wert von Variable. Falls die Variable nicht 
gesetzt ist, wird der Wert benutzt, und Variable erhält
den Wert.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \${Variable:?Wert}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Nutzt den Wert von Variable. Falls die Variable nicht 
gesetzt ist, wird der Wert ausgegeben und die Shell 
beendet. Wenn kein Wert angegeben wurde, wird der Text 
{\bf parameter null or not set} ausgegeben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \${Variable:+Wert}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Nutzt den Wert, falls die Variable gesetzt ist, 
andernfalls nichts.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
Beispiele:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ h=hoch r=runter l=}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Weist den drei Variablen Werte zu, wobei l einen 
leeren Wert erhält.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ echo \${h}sprung}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Gibt hochsprung aus. Die Klammern müssen gesetzt 
werden, damit h als Variablenname erkannt werden kann.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ echo \${h-\$r}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Gibt hoch aus, da die Variable h belegt ist.  
Ansonsten würde der Wert von r ausgegeben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ echo \${tmp-`date`}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Gibt das aktuelle Datum aus, wenn die Variable tmp
nicht gesetzt ist. (Der Befehl {\bf date} gibt das Datum 
zurück)
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ echo \${l=\$r}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Gibt runter aus, da die Variable l keinen Wert
enthält. Gleichzeitig wird l der Wert von r 
zugewiesen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$ echo \$l}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Gibt runter aus, da l jetzt den gleichen Inhalt hat 
wie r.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   
   \subsection{Quoting} \label{d73e807}
        
    

    
  \par
  
Dies ist ein sehr schwieriges Thema, da hier mehrere ähnlich aussehende
Zeichen völlig verschiedene Effekte bewirken. Unix unterscheidet allein 
zwischen drei verschiedenen Anführungszeichen. Das Quoten dient dazu, 
bestimmte Zeichen mit einer Sonderbedeutung vor der Shell zu 'verstecken' 
um zu verhindern, dass diese expandiert (ersetzt) werden.
    

    
  \par
  
Die folgenden Zeichen haben eine spezielle Bedeutung innerhalb der Shell:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ;}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Befehls-Trennzeichen
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Hintergrund-Verarbeitung
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ( )}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Befehls-Gruppierung
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf |}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Pipe
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \verb+<+ \verb+>+ \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Umlenkungssymbole
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf * ? [ ] \~{} + - @ !}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Meta-Zeichen für Dateinamen
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ` ` (Backticks)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Befehls-Substitution (Die Backticks erhält man 
durch [shift] und die Taste neben dem Backspace.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Variablen-Substitution
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [newline] [space] [tab]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wort-Trennzeichen
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Die folgenden Zeichen können zum Quoten verwendet werden:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf '' '' (Anführungszeichen)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Alles zwischen diesen Zeichen ist buchstabengetreu 
zu interpretieren. Ausnahmen sind folgende Zeichen,
die ihre spezielle Bedeutung beibehalten: {\bf \$ ` ''}
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ' ' (Ticks)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Alles zwischen diesen Zeichen wird wörtlich 
genommen, mit Ausnahme eines weiteren {\bf '}  und 
{\bf $\backslash$}.
(Die Ticks erhält man bei deutschen Tastaturen 
durch die Taste neben dem Backspace -- ohne [shift].)
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$ (Backslash)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Das Zeichen nach einem {\bf $\backslash$} wird wörtlich genommen. 
Anwendung z. B. innerhalb von {\bf '' ''}, um
{\bf ''}, {\bf \$} und {\bf `} zu
entwerten. Häufig verwendet zur Angabe von 
Leerzeichen ({\bf space}) und Zeilenendezeichen, oder um 
ein {\bf $\backslash$}-Zeichen selbst anzugeben.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
                       
    
  \par
  
Beispiele:
    
    
     \begin{tt} \begin{scriptsize} user@linux / \$ 
echo 'Ticks ''schützen'' Anführungszeichen'
      \end{scriptsize} \end{tt} \linebreak 
     \begin{tt} \begin{scriptsize} Ticks ''schützen'' Anführungszeichen\end{scriptsize} \end{tt} \linebreak
     \begin{tt} \begin{scriptsize}  \linebreak user@linux / \$ 
echo ''Ist dies ein $\backslash$''Sonderfall$\backslash$''?''
      \end{scriptsize} \end{tt} \linebreak 
     \begin{tt} \begin{scriptsize} Ist dies ein ''Sonderfall''?\end{scriptsize} \end{tt} \linebreak
     \begin{tt} \begin{scriptsize}  \linebreak user@linux / \$ 
echo ''Sie haben `ls | wc -l` Dateien in `pwd`''
      \end{scriptsize} \end{tt} \linebreak 
     \begin{tt} \begin{scriptsize} Sie haben 43 Dateien in /home/rschaten\end{scriptsize} \end{tt} \linebreak
     \begin{tt} \begin{scriptsize}  \linebreak user@linux / \$      
echo ''Der Wert von $\backslash$\$x ist \$x''
      \end{scriptsize} \end{tt} \linebreak 
     \begin{tt} \begin{scriptsize} Der Wert von \$x ist 100\end{scriptsize} \end{tt} \linebreak
    
   
   \subsection{Meta-Zeichen} \label{d73e1008}
        
    
    
  \par
  
Bei der Angabe von Dateinamen können eine Reihe von Meta-Zeichen verwendet 
werden, um mehrere Dateien gleichzeitig anzusprechen oder um nicht den vollen 
Dateinamen ausschreiben zu müssen. (Meta-Zeichen werden auch Wildcards, 
Joker-Zeichen oder Platzhalter genannt.)
     
     
  \par
  
Die wichtigsten Meta-Zeichen sind:
     
	
     
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf *}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Eine Folge von keinem, einem oder mehreren Zeichen
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ?}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein einzelnes Zeichen
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [abc]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung mit einem beliebigen Zeichen in der Klammer
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [a-q]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung mit einem beliebigen Zeichen aus dem angegebenen Bereich
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [!abc]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung mit einem beliebigen Zeichen, das nicht in der Klammer ist
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Home-Verzeichnis des aktuellen Benutzers
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}name}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Home-Verzeichnis des Benutzers name
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Aktuelles Verzeichnis
       
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}-}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Vorheriges Verzeichnis
       
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   
     
Beispiele:
     

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ls neu*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Listet alle Dateien, die mit 'neu' anfangen
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ls neu?}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Listet 'neuX', 'neu4', aber nicht 'neu10'
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ls [D-R]*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Listet alle Dateien, die mit einem Großbuchstaben zwischen D und R
anfangen (Natürlich wird in Shell-Skripten -- wie überall in der 
Unix-Welt -- zwischen Groß- und Kleinschreibung unterschieden.)
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   
   
   \subsection{Mustererkennung} \label{d73e1149}
        
    
    
  \par
  
Man unterscheidet in der Shell-Programmierung zwischen den Meta-Zeichen,
die bei der Bezeichnung von Dateinamen eingesetzt werden und den
Meta-Zeichen, die in mehreren Programmen Verwendung finden, um z. B. 
Suchmuster zu definieren. Diese Muster werden auch reguläre Ausdrücke 
({\bf regular expression}) genannt. Sie bieten wesentlich mehr Möglichkeiten als 
die relativ einfachen Wildcards für Dateinamen.
    
    
  \par
  
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zei-
chen zur Verfügung stehen. Eine ausführlichere Beschreibung der Einträge
findet sich danach.
    
	
    
    
    %table
    \begin{tabular}{|l|l|l|l|l|l|l|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf ed}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf ex}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf vi}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf sed}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf awk}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf grep}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf egrep}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf .}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ein beliebiges Zeichen
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf *}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Kein, ein oder mehrere Vorkommen des vorhergehenden Ausdrucks.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Zeilenanfang
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Zeilenende
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Hebt die Sonderbedeutung des folgenden Zeichens auf.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [ ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ein Zeichen aus einer Gruppe
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$( $\backslash$)   }
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Speichert das Muster zur späteren Wiederholung.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash${ $\backslash$}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Vorkommensbereich
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$\verb+<+ $\backslash$\verb+>+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wortanfang oder -ende
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf +}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ein oder mehrere Vorkommen des vorhergehenden Ausdrucks.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ?}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Kein oder ein Vorkommen des vorhergehenden Ausdrucks.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf |}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Trennt die für die Übereinstimmung verfügbaren Alternativen.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ( )}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Gruppiert Ausdrücke für den Test.
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
    
    
  \par
  
Bei einigen Tools ({\bf ex}, {\bf sed} und
{\bf ed}) werden zwei Muster angegeben: Ein Suchmuster
(links) und ein Ersatzmuster (rechts). Nur die folgenden Zeichen
sind in einem Ersatzmuster gültig:
    

    
    
    %table
    \begin{tabular}{|l|l|l|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf ex}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf sed}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf ed}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Sonderbedeutung des nächsten Zeichens aufheben.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Verwendet das in {\bf $\backslash$( $\backslash$)} gespeicherte Muster erneut.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Verwendet das vorherige Suchmuster erneut.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Verwendet das vorherige Ersatzmuster erneut.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$u $\backslash$U}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ändert das (die) Zeichen auf Großschreibung.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$l $\backslash$L}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ändert das (die) Zeichen auf Kleinschreibung.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$E}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Hebt das vorangegangene {\bf $\backslash$U} oder {\bf $\backslash$L} auf.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$e}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              X
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Hebt das vorangegangene {\bf $\backslash$u} oder {\bf $\backslash$l} auf.
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Sonderzeichen in Suchmustern: 
    
	
    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf .}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für ein beliebiges *einzelnes* Zeichen, mit Ausnahme 
des Zeilenendezeichens.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf *}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für eine beliebige (auch leere) Menge des einzelnen Zeichens
vor dem Sternchen. Das vorangehende Zeichen kann auch ein regulärer
Ausdruck sein. Beispielsweise steht {\bf .*} für eine beliebige Anzahl 
eines beliebigen Zeichens
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung, wenn der folgende Ausdruck am Zeilenanfang steht.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung, wenn der vorhergehende Azusdruck am Zeilenende steht.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Schaltet die Sonderbedeutung des nachfolgenden Zeichens ab.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [ ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für *ein* beliebiges Zeichen aus der eingeklammerten Gruppe.
Mit dem Bindestrich kann man einen Bereich aufeinanderfolgender
Zeichen auswählen ({\bf [a-e]}). Ein Zirkumflex ({\bf \~{}}) wirkt als Umkehrung: 
{\bf [^a-z]} erfaßt alle Zeichen, die keine Kleinbuchstaben sind. 
Ein Bindestrich oder eine schließende eckige Klammer am Listenanfang 
werden als Teil der Liste angesehen, alle anderen Sonderzeichen 
verlieren in der Liste ihre Bedeutung.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$( $\backslash$)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Speichert das Muster zwischen{\bf  $\backslash$(} und {\bf $\backslash$)} in einem speziellen Puffer.
In einer Zeile können bis zu neun solcher Puffer belegt werden.
In Substitutionen können sie über die Zeichenfolgen {\bf $\backslash$1} bis {\bf $\backslash$9} wieder
benutzt werden.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash${ $\backslash$}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für den Vorkommensbereich des unmittelbar vorhergehenden
Zeichens. {\bf $\backslash${n$\backslash$}} bezieht sich auf genau n Vorkommen, {\bf $\backslash${n,$\backslash$}} auf
mindestens n Vorkommen und {\bf $\backslash${n,m$\backslash$}} auf eine beliebige Anzahl von
Vorkommen zwischen n und m. Dabei müssen n und m im Bereich zwischen
0 und 256 liegen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$\verb+<+ $\backslash$\verb+>+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
	   Steht für ein Zeichen am Anfang ({\bf $\backslash$\verb+<+}) oder am Ende ({\bf $\backslash$\verb+>+}) eines Wortes.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf +}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für ein oder mehrere Vorkommen des vorhergehenden
regulären Ausdrucks = {\bf $\backslash${1,$\backslash$}}
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ?}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für kein oder ein Vorkommen des vorhergehenden Ausdrucks.
= {\bf $\backslash${0,1$\backslash$}}
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf |}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Übereinstimmung, wenn entweder der vorhergehende oder der 
nachfolgende reguläre Ausdruck übereinstimmen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ( )}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Steht für die eingeschlossene Gruppe von regulären Ausdrücken.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
    
    
  \par
  
Sonderzeichen in Ersatzmustern:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$    }
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Hebt die spezielle Bedeutung des nächsten Zeichens auf.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ruft das n-te Muster aus dem Puffer ab (siehe oben, unter {\bf $\backslash$( $\backslash$)}.)
Dabei ist n eine Zahl zwischen 1 und 9.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Verwendet das vorherige Suchmuster erneut als Teil eines 
Ersatzmusters.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf \~{}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Verwendet das vorherige Ersatzmuster erneut im momentanen
Ersatzmuster.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$u}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ändert das erste Zeichen des Ersatzmusters auf Großschreibung.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$U}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ändert alle Zeichen des Ersatzmusters auf Großschreibung.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$l}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ändert das erste Zeichen des Ersatzmusters auf Kleinschreibung.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$L}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ändert alle Zeichen des Ersatzmusters auf Kleinschreibung.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$e}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Hebt das vorangegangene {\bf $\backslash$u} oder {\bf $\backslash$l} auf.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$E}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Hebt das vorangegangene {\bf $\backslash$U} oder {\bf $\backslash$L} auf.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
    
    
Beispiele: Muster
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Haus}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Zeichenfolge ''Haus''.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^Haus}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Haus'' am Zeilenanfang.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Haus\$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Haus'' am Zeilenende.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^Haus\$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Haus'' als einziges Wort in einer Zeile.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [Hh]aus}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Haus'' oder ''haus''
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Ha[unl]s}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Haus'', ''Hals'' oder ''Hans''  
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [^HML]aus}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Weder ''Haus'', noch ''Maus'', noch ''Laus'',
dafür aber andere Zeichenfolgen, welche
''aus'' enthalten.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Ha.s}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Der dritte Buchstabe ist ein beliebiges Zeichen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^...\$}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Jede Zeile mit genau drei Zeichen.      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^$\backslash$.}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Jede Zeile, die mit einem Punkt beginnt.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^$\backslash$.[a-z][a-z]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Jede Zeile, die mit einem Punkt und zwei Kleinbuchstaben beginnt.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^$\backslash$.[a-z]$\backslash${2$\backslash$}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
	   Wie oben, jedoch nur in {\bf grep} und {\bf sed} zulässig.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ^[^.]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Jede Zeile, die nicht mit einem Punkt beginnt.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Fehler*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Fehle''(!), ''Fehler'', ''Fehlers'', etc.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ''Wort''}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein Wort in Anführunszeichen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ''*Wort''*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein Wort mit beliebig vielen (auch keinen)
Anführungszeichen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [A-Z][A-Z]*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein oder mehrere Großbuchstaben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [A-Z]+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben, jedoch nur in egrep und awk zulässig.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [A-Z].*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein Großbuchstabe, gefolgt von keinem oder beliebig
vielen Zeichen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [A-Z]*}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Kein, ein oder mehrere Großbuchstaben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [a-zA-Z]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ein Buchstabe.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [^0-9a-zA-Z]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Symbole (weder Buchstaben noch Zahlen).
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [0-9a-zA-Z]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Jedes alphanumerische Zeichen. 
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Beispiele:{\bf  egrep}- oder {\bf awk}-Muster
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [567]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Eine der /Zahlen 5, 6 oder 7.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf fuenf|sechs|sieben}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Eines der Worte fuenf, sechs oder sieben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 80[234]?86\verb+>+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''8086'', ''80286'', ''80386'', ''80486''.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf F(ahr|lug)zeug}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
''Fahrzeug'' oder ''Flugzeug''
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
Beispiele: {\bf ex}- oder {\bf vi}-Muster
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$\verb+<+The}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wörter wie ''Theater'' oder ''Thema''.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ung$\backslash$\verb+>+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wörter wie ''Teilung'' oder ''Endung''.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf $\backslash$\verb+<+Wort$\backslash$\verb+>+}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Das Wort ''Wort''.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Beispiele: {\bf sed}- oder {\bf grep}-Muster
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 0$\backslash${5,$\backslash$}}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Fünf oder mehr Nullen in Folge
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf [0-9]-[0-9]$\backslash${3$\backslash$}-[0-9]$\backslash${5$\backslash$}-[0-9X]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
ISBN-Nummern in der Form n-nnn-nnnnn-n, das letzte Zeichen kann
auch ein X sein.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
Beispiele: Suchen und Ersetzen mit {\bf sed} und {\bf ex}. Im Folgenden werden
Leerzeichen durch {\bf \_} und Tabulatoren durch TAB gekennzeichnet. Befehle
für {\bf ex} werden mit einem Doppelpunkt eingeleitet.
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf s/.*/( \& )/}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wiederholt die ganze Zeile, fügt aber Klammern hinzu.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf s/.*/mv \& \&.old/}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Formt eine Wortliste (ein Wort pro Zeile) zu mv-Befehlen um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf /^\$/d}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Löscht Leerzeilen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :g/^\$/d}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben, im {\bf ex}-Editor.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf /^[\_TAB]*\$/d}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Löscht Leerzeilen und Zeilen, die nur aus Leerzeichen 
oder Tabulatoren bestehen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :g/^[\_TAB]*\$/d}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben, im {\bf ex}-Editor.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf / */ /g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wandelt ein oder mehrere Leerzeichen in ein Leerzeichen um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :%s/ */ /g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben, im {\bf ex}-Editor.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :s/[0-9]/Element \&:/}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wandelt (in der aktuellen Zeile) eine Zahl in 
ein Label für ein Element um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :s}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wiederholt die Substitution beim ersten Vorkommen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :\&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :sg}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :\&g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wie oben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :%\&g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wiederholt die Substitution im ganzen Puffer.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :.,\$s/Wort/$\backslash$U\&/g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wandelt von der aktuellen bis zur letzten Zeile 
das Wort Wort in Großschreibung um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :%s/.*/$\backslash$L\&/}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wandelt die gesamte Datei in Kleinschreibung um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :s/$\backslash$\verb+<+./$\backslash$u\&/g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wandelt den ersten Buchstaben jedes Wortes 
in der aktuellen Zeile in Großschreibung um.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :%s/ja/nein/g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ersetzt das Wort ja durch nein.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf :%s/Ja/\~{}/g}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ersetzt global ein anderes Wort (Ja) durch nein 
(Wiederverwendung des vorherigen Ersatzmusters).
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   

   \subsection{Programmablaufkontrolle} \label{d73e2665}
        
    
    
  \par
  
Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei
anderen Programmiersprachen, um den Ablauf des Programms zu steuern.
Dazu gehören Funktionsaufrufe, Schleifen, Fallunterscheidungen und
dergleichen.
    
   

   \subsection{Kommentare (\#)} \label{d73e2674}
        
    
    
  \par
  
Kommentare in der Shell beginnen immer mit dem Nummern-Zeichen ({\bf \#}).
Dabei spielt es keine Rolle, ob das Zeichen am Anfang der Zeile steht, oder
hinter irgendwelchen Befehlen. Alles von diesem Zeichen bis zum Zeilenende
	 (bis auf eine Ausnahme - siehe unter 3.10).
    
   

   \subsection{Auswahl der Shell (\#!)} \label{d73e2689}
        
    
    
  \par
  
In der ersten Zeile eines Shell-Skriptes sollte definiert werden, mit welcher
Shell das Skript ausgeführt werden soll. Das System öffnet dann eine Subshell
und führt das restliche Skript in dieser aus.
    
    
  \par
  
Die Angabe erfolgt über eine Zeile in der Form {\bf \#!/bin/sh}, wobei unter 
{\bf /bin/sh} die entsprechende Shell (in diesem Fall die
{\bf Bourne-Shell}) liegt.
Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile des Skripts steht.
    
   

   \subsection{Null-Befehl (:)} \label{d73e2711}
        
    
    
  \par
  
Dieser Befehl tut nichts, außer den Status {\bf 0} zurückzugeben. Er wird benutzt,
um Endlosschleifen zu schreiben (siehe unter 3.18), oder um leere Blöcke
in {\bf if}- oder {\bf case}-Konstrukten möglich zu machen.
    
    

    
Beispiel: Prüfen, ob jemand angemeldet ist:     
    
	
	\begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
checkuser.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
if who | grep $1 > /dev/null # who: Liste der Benutzer
			     # grep: Suche nach Muster
then :			     # tut nichts
  else echo "Benutzer $1 ist nicht angemeldet"
fi
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{Source (.)} \label{d73e2744}
        
    

    
  \par
  
Der Source-Befehl wird in der Form {\bf . skriptname} angegeben. Er bewirkt
ähnliches wie ein {\bf \#include} in der Programmiersprache C.
    
    
  \par
  
Die Datei (auf die das Source ausgeführt wurde) wird eingelesen und ausgeführt,
als ob ihr Inhalt
an der Stelle des Befehls stehen würde. Diese Methode wird zum Beispiel
	 während des Bootvorgangs in den Init-Skripten benutzt, um immer wieder
benötigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem
Bildschirm etc.) in einer zentralen Datei pflegen zu können (siehe Beispiel
	 unter A.2).
    
   

   \subsection{Funktionen} \label{d73e2774}
        
    
    
  \par
  
Es ist in der Shell auch möglich, ähnlich wie in einer 'richtigen' 
Programmiersprache, Funktionen zu deklarieren und zu benutzen. Da die 
{\bf Bourne-Shell} ({\bf sh})
nicht über Aliase verfügt, können einfache Funktionen als Ersatz
dienen. Mit dem Kommando {\bf exit} (siehe unter 3.22) hat man die 
Möglichkeit, aus einer Funktion einen Wert zurückzugeben.
    
	
    
Beispiel: Die Funktion gibt die Anzahl der Dateien im aktuellen Verzeichnis
zurück. Aufgerufen wird diese Funktion wie ein Befehl, also einfach durch
die Eingabe von {\bf count}.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
countfunction.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
count () {
      ls | wc -l # ls: Liste aller Dateien im Verzeichnis
      # wc: Word-Count, zählt Wörter
}
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{Bedingungen ([ ])} \label{d73e2811}
        
    
    
  \par
  
Da die Standard-Shell keine arithmetischen oder logischen Ausdrücke 
auswerten kann, muss dazu ein externes Programm benutzt werden. ({\bf if} und 
Konsorten prüfen nur den Rückgabewert eines aufgerufenen Programmes -- 
{\bf 0} bedeutet {\bf true}, alles andere
bedeutet {\bf false}, siehe auch 3.1.2.) Dieses
Programm heißt test. Üblicherweise besteht auf allen Systemen auch noch
ein Link namens {\bf [} auf dieses Programm. Dieser Link ist absolut gleichwertig 
zu benutzen. Dementsprechend ist es auch zwingend erforderlich, nach
der Klammer ein Leerzeichen zu schreiben. Das dient dazu, Bedingungen in
{\bf if}-Abfragen u. ä. lesbarer zu machen. Um dieses Konzept der Lesbarkeit
zu unterstützen, sollte man diese öffnende Klammer auch wieder schließen
(obwohl das nicht zwingend nötig ist).
    
    
  \par
  
Das {\bf test}-Programm bietet sehr umfangreiche Optionen an. Dazu gehören
Dateitests und Vergleiche von Zeichenfolgen oder ganzen Zahlen. Diese 
Bedingungen können auch durch Verknüpfungen kombiniert werden. 
Dateitests:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -b Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist ein blockorientiertes Gerät
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -c Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist ein zeichenorientiertes Gerät
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -d Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist ein Verzeichnis
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -f Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist eine reguläre Datei
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -g Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und das Gruppen-ID-Bit ist gesetzt
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -h Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist ein symbolischer Link
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -k Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und das Sticky-Bit ist gesetzt
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -p Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist eine Named Pipe
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -r Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist lesbar
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -s Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist nicht leer
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -t [n]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Der offene Dateideskriptor n gehört zu einem Terminal; \linebreak  
          Vorgabe für n ist 1.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -u Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und das Setuid-Bis ist gesetzt
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -w Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist beschreibbar
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -x Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Datei existiert und ist ausführbar
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Bedingungen für Zeichenfolgen:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -n s1}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Länge der Zeichenfolge s1 ist ungleich Null
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf -z s1}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die Länge der Zeichenfolge s1 ist gleich Null      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf s1 = s2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Zeichenfolgen s1 und s2 sind identisch
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf s1 != s2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Zeichenfolgen s1 und s2 sind nicht identisch
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Zeichenfolge} 
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Die {\bf Zeichenfolge} ist nicht Null
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
      
Ganzzahlvergleiche:
        

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -eq n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
    n1 ist gleich n2
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -ge n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
n1 ist größer oder gleich n2
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -gt n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
n1 ist größer als n2
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -le n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
n1 ist kleiner oder gleich n2
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -lt n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
n1 ist kleiner n2
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf n1 -ne n2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
    n1 ist ungleich n2
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Kombinierte Formen:
    	   

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf (Bedingung)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wahr, wenn die Bedingung zutrifft (wird für 
die Gruppierung verwendet). Den Klammern muss 
ein $\backslash$ vorangestellt werden.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ! Bedingung  i}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wahr, wenn die Bedingung nicht zutrifft ({\bf NOT}).
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Bedingung1 -a Bedingung2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wahr, wenn beide Bedingungen zutreffen ({\bf AND}).
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Bedingung1 -o Bedingung2 }
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wahr, wenn eine der beiden Bedingungen zutrifft ({\bf OR}).
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
Beispiele:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf while test \$\# -gt 0}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Solange Argumente vorliegen. . .
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf while [ -n ''\$1'' ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Solange das erste Argument nicht leer ist. . .
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf if [ \$count -lt 10 ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wenn \$count kleiner 10. . .
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf if [ -d RCS ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wenn ein Verzeichnis RCS existiert. . .
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf if [ ''\$Antwort'' != ''j'' ]}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wenn die Antwort nicht ''j'' ist. . .
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf if [ ! -r ''\$1'' -o ! -f ''\$1'' ]} 
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Wenn das erste Argument keine lesbare oder 
reguläre Datei ist. . .
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   

   \subsection{if. . .} \label{d73e3240}
        
    
    
  \par
  
Die {\bf if}-Anweisung in der Shell-Programmierung macht das gleiche wie in
allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit
und macht davon den weiteren Ablauf des Programms abhängig.
    
    
  \par
  
	 Die Syntax der {\bf if}-Anweisung lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
if-beispiel.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
if Bedingung1
   then Befehle1
   [ elif Bedingung2
   then Befehle2 ]
   ...
   [ else Befehle3 ]
fi
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Wenn die Bedingung1 erfüllt ist, werden die Befehle1 ausgeführt; 
andernfalls,
wenn die Bedingung2 erfüllt ist, werden die Befehle2 ausgeführt. 
Trifft keine Bedingung zu, sollen die Befehle3 ausgeführt werden.
    
    
  \par
  
Bedingungen werden normalerweise mit dem Befehl {\bf test} (siehe unter
3.14) formuliert. Es kann
aber auch der Rückgabewert (siehe unter 3.1.2)
jedes anderen Kommandos ausgewertet werden. Für Bedingungen, die auf 
jeden Fall zutreffen sollen steht der
{\bf Null}-Befehl (:, siehe unter 3.11) 
zur Verfügung.
    
	
    
Beispiele: Man achte auf die Positionierung der Semikoli.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
test-beispiele.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
# Füge eine 0 vor Zahlen kleiner 10 ein:
if [ $counter -lt 10 ]; then
   number=0$counter; else number=$counter; fi

# Erstelle ein Verzeichnis, wenn es noch nicht existiert:
if [ ! -e $dir ]; then
   mkdir $dir; fi # mkdir: Verzeichnis erstellen
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{case. . .} \label{d73e3300}
        
    
    
  \par
  
Auch die {\bf case}-Anweisung ist vergleichbar in vielen anderen Sprachen 
vorhanden. Sie dient, ähnlich wie die {\bf if}-Anweisung, zur Fallunterscheidung. 
Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden 
(Entweder / Oder), sondern es sind mehrere Fälle möglich. Man kann die 
{\bf case}-Anweisung auch durch eine geschachtelte {\bf if}-Anweisung völlig umgehen, 
allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten.
    
    
  \par
  
	 Die Syntax der {\bf case}-Anweisung lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
case-beispiel-simpel.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh     
case Wert in
     Muster1) Befehle1;;
     Muster2) Befehle2;;
     ...
esac
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
    
  \par
  
Wenn der Wert mit dem Muster1 übereinstimmt, wird die entsprechende 
Befehlsgruppe (Befehle1) ausgeführt, bei Übereinstimmung mit Muster2
werden die Kommandos der zweiten Befehlsgruppe (Befehle2) ausgeführt,
usw. Der letzte Befehl in jeder Gruppe muss mit ;; gekennzeichnet werden.
Das bedeutet für die Shell soviel wie {\bf springe zum nächsten esac}, so dass die
anderen Bedingungen nicht mehr überprüft werden.
    
    
  \par
  
In den Mustern sind die gleichen Meta-Zeichen erlaubt wie bei der Auswahl
von Dateinamen. Wenn in einer Zeile mehrere Muster angegeben werden 
sollen, müssen sie durch ein Pipezeichen ({\bf |}, logisches ODER) getrennt
werden.
    
	
    
Beispiele:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
case-beispiel-fortgeschritten.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
# Mit dem ersten Argument in der Befehlszeile 
# wird die entsprechende Aktion festgelegt:

case $1 in # nimmt das erste Argument
     Ja|Nein) response=1;;
	      -[tT]) table=TRUE;;
	   *) echo "Unbekannte Option"; exit 1;;
esac

# Lies die Zeilen von der Standardeingabe, bis eine 
# Zeile mit einem einzelnen Punkt eingegeben wird:

while : # Null-Befehl (immer wahr, siehe unter 3.11)

do
	echo "Zum Beenden . eingeben ==> \c"
	read line # read: Zeile von StdIn einlesen
	case "$line" in
	     .) echo "Ausgefuehrt"
	        break;;
	     *) echo "$line" >> $message ;;
	esac
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{for. . .} \label{d73e3360}
        
    
    
  \par
  
Dieses Konstrukt ähnelt nur auf den ersten Blick seinen Pendants aus 
anderen Programmiersprachen. In anderen Sprachen wird die {\bf for}-Schleife 
meistens dazu benutzt, eine Zählvariable über einen bestimmten Wertebereich
iterieren zu lassen ({\bf for i = 1 to 100...next}). In der Shell dagegen wird
die Laufvariable nicht mit aufeinanderfolgenden Zahlen belegt, sondern mit
einzelnen Werten aus einer anzugebenden Liste. (Wenn man trotzdem eine
Laufvariable braucht, muss man dazu die {\bf while}-Schleife {\bf mißbrauchen},
siehe unter 3.18)
    
    
  \par
  
Die Syntax der {\bf for}-Schleife lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
for-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
for x [ in Liste ]
do
	Befehle
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Die Befehle werden ausgeführt, wobei der Variablen x nacheinander die
Werte aus der Liste zugewiesen werden. Wie man sieht ist die Angabe der
Liste optional, wenn sie nicht angegeben wird, nimmt x der Reihe nach alle
Werte aus {\bf \$@} (in dieser vordefinierten Variablen liegen die Aufrufparameter 
- siehe unter 3.3) an. Wenn die Ausführung eines Schleifendurchlaufs
bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos
{\bf continue} (3.20) bzw. {\bf break}
(3.21) benutzt werden. \linebreak 
	 Beispiele:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
for-beispiele.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh     
# Seitenweises Formatieren der Dateien, die auf der 
# Befehlszeile angegeben wurden, und speichern des 
# jeweiligen Ergebnisses:

for file do
    pr $file > $file.tmp # pr: Formatiert Textdateien
done

# Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):

for item in `cat program_list` # cat: Datei ausgeben
do
	echo "Pruefung der Kapitel auf"
	echo "Referenzen zum Programm $item ..."
	grep -c "$item.[co]" chap* # grep: nach Muster suchen
done

# Ermittle einen Ein-Wort-Titel aus jeder Datei und 
# verwende ihn als neuen Dateinamen:

for file do
    name=`sed -n 's/NAME: //p' $file`
    # sed: Skriptsprache zur
    # Textformatierung
    mv $file $name 
    # mv: Datei verschieben
    # bzw. umbenennen
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{while. . .} \label{d73e3431}
        
    
    
  \par
  
Die {\bf while}-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen
Sprachen bekannt ist: Die {\bf kopfgesteuerte} Schleife.
    
    
  \par
  
Die Syntax der while-Schleife lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
while-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
while Bedingung
do
	Befehle
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Die Befehle werden so lange ausgeführt, wie die Bedingung erfüllt ist.
Dabei wird die Bedingung vor der Ausführung der Befehle überprüft. Die
Bedingung wird dabei üblicherweise, genau wie bei der {\bf if}-Anweisung, 
mit dem Befehl {\bf test} (siehe unter 3.14) formuliert.
Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll,
müssen die Kommandos {\bf continue} (3.20) bzw.
{\bf break} (3.21) benutzt werden. \linebreak 
Beispiel:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
while-beispiel01.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
# Zeilenweise Ausgabe aller Aufrufparameter:

while [ -n "$1"]; do
      echo $1
      shift	# mit shift werden die Parameter nach
		# Links geshiftet (aus $2 wird $1)
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Eine Standard-Anwendung der {\bf while}-Schleife ist der Ersatz für die 
Zählschleife. In anderen Sprachen kann man mit der {\bf for}-Schleife eine 
Zählvariable über einen bestimmten Wertebereich iterieren lassen 
({\bf for i = 1 to 100...next}). Da das mit der {\bf for}-Schleife der Shell nicht geht,
ersetzt man die Funktion durch geschickte Anwendung der {\bf while}-Schleife:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
while-beispiel02.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh    
# Ausgabe der Zahlen von 1 bis 100:

i=1
while [ $i -le 100 ]
do
	echo $i
	i=`expr $i + 1`
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{until. . .} \label{d73e3520}
        
    
    
  \par
  
Die {\bf until}-Schleife ist das Gegenstück zur {\bf while}-Schleife: Die ebenfalls aus
vielen anderen Sprachen bekannte {\bf fußgesteuerte} Schleife.
    
    
  \par
  
Die Syntax der {\bf until}-Schleife lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
until-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh    
until Bedingung
do
	Befehle
done
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
    
  \par
  
Die Befehle werden ausgeführt, bis die Bedingung erfüllt ist. Dabei wird
die Bedingung nach der Ausführung der Befehle überprüft. Die Bedingung
wird dabei üblicherweise, genau wie bei der {\bf if}-Anweisung, mit dem Befehl
{\bf test} (siehe unter 3.14) formuliert. Wenn die Ausführung eines 
Schleifendurchlaufs bzw der ganzen Schleife abgebrochen werden soll, müssen 
die Kommandos {\bf continue} (3.20) bzw. {\bf break}
(3.21) benutzt werden.
    
	
    
Beispiel: Hier wird die Bedingung nicht per {\bf test} sondern mit dem 
Rückgabewert des Programms {\bf grep} formuliert.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
until-beispiel.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh     
# Warten, bis sich der Administrator einloggt:

until who | grep "root"; do
      # who: Liste der Benutzer
      # grep: Suchen nach Muster
      sleep 2 # sleep: warten
done
echo "Der Meister ist anwesend"
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   

   \subsection{continue} \label{d73e3595}
        
    
    
  \par
  
	 Die Syntax der {\bf continue}-Anweisung lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
continue-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
             
#!/bin/sh
continue [ n ]
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Man benutzt {\bf continue} um die restlichen Befehle in einer Schleife zu
überspringen und mit dem nächsten Schleifendurchlauf anzufangen. Wenn
der Parameter n angegeben wird, werden n Schleifenebenen übersprungen.
    
   
   
   \subsection{break} \label{d73e3622}
        
    
    
  \par
  
Die Syntax der {\bf break}-Anweisung lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
break-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
             
break [ n ]
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Mit {\bf break} kann man die innerste Ebene (bzw. n Schleifenebenen) verlassen 
ohne den Rest der Schleife auszuführen.
    
   

   \subsection{exit} \label{d73e3649}
        
    
    
  \par
  
Die Syntax der {\bf exit}-Anweisung lautet wie folgt:
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
exit-syntax.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
exit [ n ]
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Die {\bf exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der
Parameter n angegeben wird, wird er von dem Skript als Exit-Code 
zurückgegeben.
    
   

   \subsection{Befehlsformen} \label{d73e3676}
        
    
    
  \par
  
Es gibt eine Reihe verschiedener Möglichkeiten, Kommandos auszuführen:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Ausführung von Befehl im Hintergrund
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 ; Befehl2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Befehlsfolge, führt mehrere Befehle in einer Zeile aus
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf (Befehl1 ; Befehl2)}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Subshell, behandelt Befehl1 und Befehl2 als Befehlsfolge
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 | Befehl2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Pipe, verwendet die Ausgabe von Befehl1 als Eingabe für Befehl2
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 `Befehl2`}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Befehls-Substitution, verwendet die Ausgabe von 
Befehl2 als Argumente für Befehl1
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 \&\& Befehl2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf AND}, führt zuerst Befehl1 und dann (wenn Befehl1 
erfolgreich war) Befehl2 aus
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 || Befehl2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf OR}, entweder Befehl1 ausführen oder 
Befehl2 (Wenn Befehl1 nicht erfolgreich war)
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf { Befehl1 ; Befehl2 }}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Ausführung der Befehle in der momentanen Shell
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
Beispiele:
    


    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf nroff Datei \&}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Formatiert die Datei im Hintergrund
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf cd; ls}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Sequentieller Ablauf
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf (date; who; pwd) \verb+>+ logfile}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Lenkt alle Ausgaben um
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf sort Datei | lp}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Sortiert die Datei und druckt sie
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf vi `grep -l ifdef *.c`}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Editiert die mittels grep gefundenen Dateien
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf grep XX Datei \&\& lp Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Druckt die Datei, wenn sie XX enthält
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf grep XX Datei || lp Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Druckt die Datei, wenn sie XX nicht enthält
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
   

   \subsection{Datenströme} \label{d73e3848}
        
    
    
  \par
  
Eines der markantesten Konzepte, das in Shell-Skripten benutzt wird, ist
das der Datenströme. Die meisten der vielen Unix-Tools bieten die 
Möglichkeit, Eingaben aus der sogenannten {\bf Standard-Eingabe} entgegenzunehmen
und Ausgaben dementsprechend auf der {\bf Standard-Ausgabe} zu machen. Es
gibt noch einen dritten Kanal für Fehlermeldungen, so dass man eine einfache
Möglichkeit hat, fehlerhafte Programmdurchläufe zu behandeln indem man
die Fehlermeldungen von den restlichen Ausgaben trennt.
    
    
  \par
  
Es folgt eine Aufstellung der drei Standardkanäle:
     


    
    
    %table
    \begin{tabular}{|l|l|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Datei-Deskriptor}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf Name}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf Gebräuchliche Abkürzung}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf Typischer Standard}
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 0}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Standardeingabe
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              stdin
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Tastatur
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 1}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Standardausgabe
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              stdout
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Terminal
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Fehlerausgabe
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              stderr
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Terminal
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Die standardmäßige Eingabequelle oder das Ausgabeziel können wie folgt
geändert werden:
    

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Einfache Umlenkung:}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+>+ Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standardausgabe von Befehl in Datei schreiben. 
Die Datei wird überschrieben, wenn sie schon bestand.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+>+\verb+>+ Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standardausgabe von Befehl an Datei anhängen. 
Die Datei wird erstellt, wenn sie noch nicht bestand.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+<+ Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standardeingabe für Befehl aus Datei lesen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl1 | Befehl2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Standardausgabe von Befehl1 wird an die 
Standardeingabe von Befehl2 übergeben. Mit diesem 
Mechanismus können Programme als {\bf Filter} für den 
Datenstrom eingesetzt werden. Das verwendete Zeichen 
heißt {\bf Pipe}.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
	
  \par
  
	
    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Umlenkung mit Hilfe von Datei-Deskriptoren:}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+>+\&n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standard-Ausgabe von Befehl an den Datei-Deskriptor n 
übergeben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl m\verb+>+\&n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Der gleiche Vorgang, nur wird die Ausgabe, die normalerweise 
an den Datei-Deskriptor m geht, an den Datei-Deskriptor n 
übergeben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+>+\&-}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Schließt die Standard-Ausgabe.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+<+\&n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standard-Eingabe für Befehl wird vom Datei-Deskriptor n 
übernommen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl m\verb+<+\&n}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Der gleiche Vorgang, nur wird die Eingabe, die normalerweise 
vom Datei-Deskriptor m stammt, aus dem Datei- Deskriptor n 
übernommen.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+<+\&-}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Schließt die Standard-Eingabe.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  
	
	
  \par
  
	

    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Mehrfach-Umlenkung:}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl 2\verb+>+ Datei}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Fehler-Ausgabe von Befehl in Datei schreiben.  
Die Standard-Ausgabe bleibt unverändert 
(z. B.  auf dem Terminal).
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl \verb+>+ Datei 2\verb+>+\&1}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Fehler-Ausgabe und Standard-Ausgabe von Befehl werden 
in die Datei geschrieben.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf (Befehl \verb+>+ D1) 2\verb+>+D2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Standard-Ausgabe erfolgt in die Datei D1; 
Fehler-Ausgabe in die Datei D2.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Befehl | tee Dateien}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Ausgaben von Befehl erfolgen an der 
Standard-Ausgabe (in der Regel: Terminal), 
zusätzlich wird sie vom Kommando {\bf tee} in die Dateien 
geschrieben.  
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Zwischen den Datei-Deskriptoren und einem Umlenkungssymbol darf kein 
Leerzeichen sein; in anderen Fällen sind Leerzeichen erlaubt. \linebreak 
Beispiele:
    
    
    
    %table
    \begin{tabular}{|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf cat Datei1 \verb+>+ Neu}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Schreibt den Inhalt der Datei1 in die Datei Neu.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf cat Datei2 Datei3 \verb+>+\verb+>+ Neu}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Hängt den Inhalt der Datei2 und der Datei3 
an die Datei Neu an.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf mail name \verb+<+ Neu}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Das Programm mail liest den Inhalt der Datei Neu.
      
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf ls -l | grep ''txt'' | sort}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              
Die Ausgabe des Befehls {\bf ls -l} 
(Verzeichnisinhalt) wird an das Kommando grep 
weitergegeben, das darin nach {\bf txt} sucht. 
Alle Zeilen, die das Muster enthalten, werden 
anschließend an sort übergeben und landen dann 
sortiert auf der Standardausgabe.
      
		\end{minipage}
	      \\ \hline
    \end{tabular}
  

    
  \par
  
Gerade der Mechanismus mit dem Piping sollte nicht unterschätzt werden. Er 
dient nicht nur dazu, relativ kleine Texte zwischen Tools hin- und
herzureichen. An dem folgenden Beispiel soll die Mächtigkeit dieses kleinen
Zeichens gezeigt werden:
    
    
  \par
  
Es ist mit den passenden Tools unter Unix möglich, eine ganze Audio-CD
mit zwei Befehlen an der Kommandozeile zu duplizieren. Das erste 
Kommando veranlaßt, dass die TOC (Table Of Contents) der CD in die Datei
{\bf cd.toc} geschrieben wird. Das dauert nur wenige Sekunden. Die Pipe steckt im
zweiten Befehl. Hier wird der eigentliche Inhalt der CD mit dem Tool 
{\bf cdparanoia} ausgelesen. Da kein Dateiname angegeben
schreibt {\bf cdparanoia}
die Daten auf seine Standardausgabe. Diese wird von dem Brennprogramm
{\bf cdrdao} übernommen und in Verbindung mit der TOC 
{\bf on the fly} auf die CD geschrieben.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
cd-kopieren.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
cdrdao read-toc --datafile - cd.toc
cdparanoia -q -R 1- - | cdrdao write --buffers 64 cd.toc
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   
  \section{Wo sind Unterschiede zu DOS-Batchdateien?} \label{d73e4218}
        
   
   
  \par
   
Unter DOS werden Batch-Dateien oft dazu benutzt, lange Kommandos abzukürzen 
um die Tipparbeit zu vermindern, oder um sich das Merken von
vielen Parametern zu ersparen. Diese Aufgabe überläßt man unter Unix am
besten den {\bf Shell-Aliasen}.
    
   
  \par
   
Shell-Skripte können viel mehr als Batch-Dateien.
    
   
  \par
   
Wie der Name schon sagt, sind Batch-Dateien im Wesentlichen nur ein
{\bf Stapel} von Anweisungen, die nacheinander ausgeführt werden. Mit neueren
DOS-Versionen sind zwar auch einige einfache Mechanismen zur Verzweigung
hinzugekommen, aber das entspricht bei weitem nicht den Möglichkeiten, die
man an der Shell hat.
    
   
  \par
   
Shell-Skripte kann man dagegen eher mit einer {\bf richtigen} 
Programmiersprache vergleichen. Es stehen alle Konstrukte zur Verfügung, 
die eine Programmiersprache auszeichnen (Funktionen, Schleifen, Fallunterscheidungen,
Variablen, etc).
    
  \section{Anhang A: Beispiele} \label{d73e4254}
        
   
   \subsection{Schleifen und Rückgabewerte} \label{d73e4259}
        
    
    
  \par
  
Man kann mit einer {\bf until}- bzw. mit einer {\bf while}-Schleife schnell kleine aber
sehr nützliche Tools schreiben, die einem lästige Aufgaben abnehmen.
    
    \subsubsection{Schleife, bis ein Kommando erfolgreich war} \label{d73e4273}
        
     
     
  \par
  
Angenommen, bei der Benutzung eines Rechners tritt ein Problem auf, bei
dem nur der Administrator helfen kann. Dann möchte man informiert werden,
sobald dieser an seinem Arbeitsplatz ist. Man kann jetzt in regelmäßigen
Abständen das Kommando {\bf who} ausführen, und dann in der Ausgabe nach
dem Eintrag {\bf root} suchen. Das ist aber lästig.
     
     
  \par
  
Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30
Sekunden automatisch überprüft, ob der Admin angemeldet ist. Wir errei-
chen das mit dem folgenden Code:
     

     \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
auf-root-warten.sh
      \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
until who | grep "^root "
      do sleep 30
done
echo Big Brother is watching you!
      \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

     
  \par
  
Das Skript führt also so lange das Kommando aus, bis die Ausführung
erfolgreich war. Dabei wird die Ausgabe von
{\bf who} mit einer Pipe (3.24) in
das {\bf grep}-Kommando umgeleitet. Dieses sucht darin nach einem Auftreten
von {\bf root} am Zeilenanfang. Der Rückgabewert von
{\bf grep} ist {\bf 0} wenn das
Muster gefunden wird, {\bf 1} wenn es nicht gefunden wird
und {\bf 2} wenn ein Fehler
auftrat. Damit der Rechner nicht die ganze Zeit mit dieser Schleife 
beschäftigt ist, wird im Schleifenkörper ein sleep 30 ausgeführt, 
um den Prozeß für 30 Sekunden schlafen zu schicken. Sobald der Admin 
sich eingeloggt hat, wird eine entsprechende Meldung ausgegeben.
     
    
    \subsubsection{Schleife, bis ein Kommando nicht erfolgreich war} \label{d73e4327}
        
     
     
  \par
  
Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben,
das meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur
die {\bf until}-Schleife durch eine entsprechende {\bf while}-Schleife:
     

     \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
warten-bis-root-verschwindet.sh
      \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/bin/sh
while who | grep "^root "
      do sleep 30
done
echo Die Katze ist aus dem Haus, Zeit, dass die Mäuse tanzen!
      \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

     
  \par
  
Die Schleife wird nämlich dann so lange ausgeführt, bis {\bf grep} einen Fehler
(bzw. eine erfolglose Suche) zurückmeldet.
     
    
   

   \subsection{Ein typisches Init-Skript} \label{d73e4358}
        
    
    
  \par
  
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird
während des Bootvorgangs gestartet, wenn der dazugehörige Runlevel 
initialisiert wird.
    
    
  \par
  
Das Skript muss mit einem Parameter aufgerufen werden. Möglich sind
hier {\bf start}, {\bf stop},
{\bf status}, {\bf restart} und {\bf reload}. Wenn falsche Parameter 
übergeben wurden, wird eine entsprechende Meldung angezeigt.
    
    
  \par
  
Das Ergebnis der Ausführung wird mit Funktionen dargestellt, die aus
der Datei {\bf /etc/rc.d/init.d/functions} stammen. Ebenfalls in dieser Datei
sind Funktionen, die einen Dienst {\bf starten} oder {\bf stoppen}.
    
    
  \par
  
Zunächst wird festgelegt, dass dieses Skript in der {\bf Bourne-Shell} ausgeführt
	 werden soll (3.24).
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
#!/bin/sh
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
   
Dann folgen Kommentare, die den Sinn des Skriptes erläutern (3a.9).
     
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
## Startup script for the Apache Web Server
#
# chkconfig: 345 85 15
# description: Apache is a World Wide Web server. It is \
#              used to serve HTML files and CGI
#
# processname: httpd
# pidfile: /var/run/httpd.pid
# config: /etc/httpd/conf/access.conf
# config: /etc/httpd/conf/httpd.conf
# config: /etc/httpd/conf/srm.conf
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Jetzt wird die Datei mit den Funktionen eingebunden (3.13).
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
# Source function library.
/etc/rc.d/init.d/functions
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
	 Hier werden die Aufrufparameter ausgewertet (3.17).
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
# See how we were called.
case "$1" in
     start)
	echo -n "Starting httpd: "
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Nachdem eine Meldung über den auszuführenden Vorgang ausgegeben
wurde, wird die Funktion {\bf daemon} aus der Funktionsbibliothek ausgeführt.
Diese Funktion startet das Programm, dessen Name hier als Parameter
übergeben wird. Dann gibt sie eine Meldung über den Erfolg aus.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        daemon httpd
        echo
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Jetzt wird ein Lock-File angelegt. (Ein Lock-File signalisiert anderen 
Prozessen, dass ein bestimmter Prozeß bereits gestartet ist. So kann ein 
zweiter Aufruf verhindert werden.)
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        touch /var/lock/subsys/httpd
	;;
      stop)
        echo -n "Shutting down http: "
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Hier passiert im Prinzip das gleiche wie oben, nur dass mit der Funktion
{\bf killproc} der Daemon angehalten wird.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        killproc httpd
        echo
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Danach werden Lock-File und PID-File gelöscht. (In einem sogenannten PID-File 
hinterlegen einige Prozesse ihre Prozeß-ID, um anderen Programmen den
Zugriff zu erleichtern, z.B. um den Prozeß anzuhalten etc.)
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        rm -f /var/lock/subsys/httpd
        rm -f /var/run/httpd.pid
        ;;
    status)
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Die Funktion {\bf status} stellt fest, ob der entsprechende Daemon bereits läuft,
und gibt das Ergebnis aus.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        status httpd
        ;;
   restart)
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Bei Aufruf mit dem Parameter {\bf restart} ruft sich das Skript zwei mal selbst
auf (in {\bf \$0} steht der Aufrufname des laufenden Programms). Einmal, um
den Daemon zu {\bf stoppen}, dann, um ihn wieder zu {\bf starten}.
     
     \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
      \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        $0 stop
        $0 start
        ;;
    reload)
        echo -n "Reloading httpd: "
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Hier sendet die {\bf killproc}-Funktion dem Daemon ein Signal das ihm sagt,
dass er seine Konfiguration neu einlesen soll.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        killproc httpd -HUP
        echo
        ;;
         *)
        echo "Usage: $0 {start|stop|restart|reload|status}"
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Bei Aufruf mit einem beliebigen anderen Parameter wird eine Kurzhilfe
ausgegeben. Dann wird dafür gesorgt, dass das Skript mit dem Exit-Code 1
beendet wird. So kann festgestellt werden, ob das Skript ordnungsgemäß
	 beendet wurde (3.22).
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
beispiel.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
        exit 1
esac
exit 0
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   
   \subsection{Parameterübergabe in der Praxis} \label{d73e4584}
        
    
    
  \par
  
Es kommt in der Praxis sehr oft vor, dass man ein Skript schreibt, dem der
Anwender Parameter übergeben soll. Wenn das nur eine Kleinigkeit ist (zum
Beispiel ein Dateiname), dann fragt man einfach die entsprechenden 
vordefinierten Variablen (3.3) ab.
Sollen aber {\bf richtige} Parameter 
eingesetzt werden, die sich so einsetzen lassen wie man es von vielen 
Kommandozeilentools gewohnt ist, dann benutzt man das Hilfsprogramm 
{\bf getopt}. Dieses Programm parst die originalen
Parameter und gibt sie in {\bf standardisierter} Form zurück.
    
    
  \par
  
Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die
Optionen {\bf -a} und {\bf -b}. Letzterer Option muss ein zusätzlicher Wert mitgegeben
werden. Alle anderen Parameter werden als Dateinamen interpretiert.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
getopt.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
#!/bin/sh
set -- `getopt "ab:" "$@"` || {
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Das {\bf set}-Kommando belegt den Inhalt der
vordefinierten Variablen (3.3)
neu, so dass es aussieht, als ob dem Skript die Rückgabewerte von {\bf getopt}
übergeben wurden. Man muss die beiden Minuszeichen angeben, da sie
dafür sorgen, dass die Aufrufparameter an getopt und nicht an die Shell
selbst übergeben werden. Die originalen Parameter werden von {\bf getopt}
untersucht und modifiziert zurückgegeben: a und b werden als Parameter
Markiert, b sogar mit der Möglichkeit einer zusätzlichen Angabe.
    
    
  \par
  
Wenn dieses Kommando fehlschlägt ist das ein Zeichen dafür, dass falsche
Parameter übergeben wurden. Also wird nach einer entsprechenden
Meldung das Programm mit Exit-Code 1 verlassen.
    
	
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
getopt.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
       echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2
       exit 1
}
echo "Momentan steht in der Kommandozeile folgendes: $*"
aflag=0 name=NONE
while :
do
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
In einer Endlos-Schleife, die man mit Hilfe des Null-Befehls (:,
3.11) baut,
werden die {\bf neuen} Parameter der Reihe nach untersucht. Wenn ein {\bf -a}
vorkommt, wird die Variable {\bf aflag} gesetzt. Bei einem {\bf -b} werden per shift
alle Parameter nach Links verschoben, dann wird der Inhalt des nächsten
Parameters in der Variablen name gesichert.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
getopt.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
       case "$1" in
	    -a) aflag=1 ;;
	    -b) shift; name="$1" ;;
	    --) break ;;
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Wenn ein {\bf --} erscheint, ist das ein Hinweis darauf, dass die Liste der
Parameter abgearbeitet ist. Dann wird per
{\bf break} (3.21) die Endlosschleife
unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell
angegebenen Dateinamen, die von dem restlichen Skript wie gewohnt
weiterverarbeitet werden können.

   
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
getopt.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
       esac
       shift
done
shift
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
    
  \par
  
Am Ende werden die Feststellungen ausgegeben.
    
    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
getopt.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
echo "aflag=$aflag / Name = $name / Die Dateien sind $*"	
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   
     
   \subsection{Fallensteller: Auf Traps reagieren} \label{d73e4710}
        
    
    
  \par
  
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste 
(normalerweise [
	 {\bf 
	  CTRL+C
	}
]) unterbrochen werden. Durch Druck auf diese Taste
wird ein Signal an den entsprechenden Prozeß gesandt, das ihn bittet sich
zu beenden. Dieses Signal heißt SIGINT (für SIGnal INTerrupt) und trägt
die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript
sich temporäre Dateien angelegt hat, da diese nach der Ausführung nur noch
unnötig Platz verbrauchen und eigentlich gelöscht werden sollten. Man kann
sich sicher auch noch wichtigere Fälle vorstellen, in denen ein Skript be-
stimmte Aufgaben auf jeden Fall erledigen muss, bevor es sich beendet.
    
    
  \par
  
Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle
sind in der Man-Page von signal beschrieben. Hier die wichtigsten:
    

    
    
    %table
    \begin{tabular}{|l|l|l|}
    \hline 
            
               
		\begin{minipage}{60mm}
              {\bf Nummer}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf Name}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              {\bf Bedeutung}
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 0}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Normal Exit
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wird durch das exit-Kommando ausgelöst.
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 1}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              SIGHUP
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wenn die Verbindung abbricht (z.B. wenn das Terminal
geschlossen wird).
    
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 2}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              SIGINT
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Zeigt einen Interrupt an ([
	   {\bf 
		CTRL+C
	  }
	   ]).
		\end{minipage}
	      \\ \hline 
            
               
		\begin{minipage}{60mm}
              {\bf 15}
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              SIGTERM
		\end{minipage}
	      & 
            
               
		\begin{minipage}{60mm}
              Wird vom {\bf kill}-Kommando gesendet.
		\end{minipage}
	      \\ \hline
    \end{tabular}
      

    
  \par
  
Wie löst man jetzt dieses Problem? Glücklicherweise verfügt die Shell über
das {\bf trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann.
Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
     
     
  \par
  
Das Skript soll eine komprimierte Textdatei mittels zcat in ein temporäres 
File entpacken, dieses mit {\bf pg} seitenweise anzeigen und nachher wieder 
löschen.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
zeige-komprimierte-datei.sh
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
#!/bin/sh
stat=1
temp=/tmp/zeige$$
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Zunächst werden zwei Variablen belegt, die im weiteren Verlauf benutzt
werden sollen. In stat wird der Wert abgelegt, den das Skript Falle
eines Abbruchs als Exit-Status zurückliefern soll. Die Variable temp enthält
den Namen für eine temporäre Datei. Dieser setzt sich zusammen aus
{\bf /tmp/zeige} und der Prozeßnummer des laufenden Skripts. So soll
sichergestellt werden, dass noch keine Datei mit diesem Namen existiert.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
zeige-komprimierte-datei.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
trap 'rm -f $temp; exit $stat' 0
trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Hier werden die {\bf Traps} definiert. Bei Signal {\bf 0} wird die temporäre Datei
gelöscht und der Wert aus der Variable stat als Exit-Code zurückgegeben.
Dabei wird dem {\bf rm}-Kommando der Parameter {\bf -f} mitgegeben, damit keine
Fehlermeldung ausgegeben wird, falls die Datei (noch) nicht existiert.
Dieser Fall tritt bei jedem Beenden des Skriptes auf, also sowohl bei einem
normalen Ende, als auch beim Exit-Kommando, bei einem Interrupt oder
bei einem {\bf Kill}. Der zweite {\bf Trap}
reagiert auf die Signale {\bf 1}, {\bf 2} und {\bf 15}. Das
heißt, er wird bei jedem unnormalen Ende ausgeführt. Er gibt eine
entsprechende Meldung auf die Standard-Fehler-Ausgabe
(3.10) aus.
Danach wird das Skript beendet, und der erste {\bf Trap} wird ausgeführt.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
zeige-komprimierte-datei.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
case $# in
    1) zcat "$1" > $temp
       pg $temp
       stat=0
       ;;
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

    
  \par
  
Jetzt kommt die eigentliche Funktionalität des Skriptes: Das
case-Kommando (3.16) testet die Anzahl der übergebenen Parameter.
Wenn genau ein Parameter übergeben wurde, entpackt {\bf zcat} die Datei, die
im ersten Parameter angegeben wurde, in die temporäre Datei. Dann folgt
die seitenweise Ausgabe mittels {\bf pg}. Nach Beendigung der Ausgabe wird der
Status in der Variablen auf {\bf 0} gesetzt, damit beim Skriptende der korrekte
Exit-Code zurückgegeben wird.
    

    \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
zeige-komprimierte-datei.sh (Fortsetzung)
     \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
               
    *) echo "Anwendung: `basename $0` Dateiname" 1gt;&2
esac
     \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
      
    
  \par
  
Wenn {\bf case} eine andere Parameterzahl feststellt, wird eine Meldung mit der
Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
    	     
   
  \section{Anhang B} \label{d73e4937}
        
   
   \subsection{Quellen} \label{d73e4942}
        
    
    \begin{list}{*}{}
     
	\item Bash Reference Manual
     (
	   http://www.gnu.org/manual/bash-2.02/bashref.html)
     
	\item Unix In A Nutshell
	  (
	   http://www.oreilly.com/catalog/unixnut3/)
     
	\item Unix Power Tools
	  (
	   http://www.oreilly.com/catalog/upt2/)
     
	\item Von DOS nach Linux HOWTO
	  (
	   http://www.tu-harburg.de/semb2204/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html)
    \end{list}
    
   
	\ref{inhalt.tex}


	\end{document}
	
