Initial revision

This commit is contained in:
rschaten 2001-07-02 12:52:18 +00:00
commit 961448f7ce
61 changed files with 2500 additions and 0 deletions

402
Makefile Normal file
View File

@ -0,0 +1,402 @@
#
# LaTeX Makefile
# --------------
#
# Author : s.m.vandenoord@student.utwente.nl (Stefan van den Oord)
# Date : July 15, 1999
#
# This Makefile is a generic makefile for LaTeX documents. Distribute it
# as you wish, but please don't edit or remove this initial comment.
#
# The Makefile can be used by setting the environment variable "MAKEFILES",
# e.g. export MAKEFILES=~/data/TeX/Makefile.
# It requires GNU Make and bash or better, like zsh. Simply sh is not
# sufficient, I believe. The first few lines of the Makefile contains
# the executables that are used, edit them to point to the executables
# on your system.
#
# DISCLAIMER: Using this Makefile is fully at your own risk. I am not
# responsible for anything! So if crucial files are removed
# by the Makefile, it is your own problem. But you should
# have backups anyway. :-)
#
# Usage
# -----
# The Makefile can do the following things for you:
# - generate PostScript equivalents of XFig figures;
# - run makeindex and BibTeX, but only if necessary;
# - compile the .dvi file, running LaTeX as many times as needed;
# - run XDvi with the compiled .dvi file;
# - create a PostScript equivalent of the .dvi file;
# - generate a HTML equivalent of the .dvi file (if Latex2HTML is
# installed);
# - remove all generated output.
# The Makefile is in some points even RCS aware.
#
# In many cases, you don't even have to tell the Makefile which LaTeX
# file it has to compile. The Makefile uses the following strategy:
# 1. Check if the environment variable LATEXTARGET is set; if it is,
# generate $LATEXTARGET.dvi.
# 2. If there is only one .tex file, use that one.
# 3. Check if there is a LaTeX file that has the same basename as the
# directory. For example, if the directory is named "Thesis" and
# there is a file "Thesis.tex", "Thesis.dvi" is generated.
#
# Invocation
# ----------
# When the MAKEFILES environment variable is set, you can use the
# following commands:
# - make latexhelp
# Prints an overview of the available commands.
# - make latexfigures
# Only generate the PostScript equivalents of XFig figures.
# - make file.dvi
# Generates the specified DVI file.
# - make file.ps
# Generates the DVI file and then runs dvips.
# - make latex
# Use the above explained strategy to find out what has to be
# generated, and generate it.
# - make view
# Do a make latex and then run XDvi.
# - make latexps
# Do a make latex and then run dvips.
# - make html
# Do a make latex and then use LaTeX2HTML to create the HTML equivalent.
# To do this, the following environment variables are used:
# * HTMLDIR : the base dir in which the output is written. For example,
# if HTMLDIR=~/public_html/LaTeX, and the file that is
# generated is "Thesis", the output will be written in the
# directory ~/public_html/LaTeX/Thesis.
# * LATEX2HTML_OPTS : if you want to pass options to LaTeX2HTML, put
# them in this variable.
# - make latexclean
# This command removes all generated output. CAUTION: the files that are
# removed are thought out pretty well, but it is possible that files are
# removed that you wanted to keep! Check below what files are removed if
# you want to be certain!
# Note that a file figure.eps is only removed if a file figure.fig exists.
# (Even if the file figure.fig exists, but is checked in using RCS, the
# file figure.eps will be removed.)
#
# Tip
# ---
# For some projects it is useful to have a separate Makefile in the project's
# directory. For example, when you use RCS, you could add functionality for
# automatic checkouts of the right files (adding dependencies is sufficient;
# GNU Make rocks :-).
# The command "latexclean" is declared so that you can add your own
# functionality in the project's Makefile; instead of one colon, declare it
# with two colons if you want to do that.
# For example:
# latexclean::
# rm -f foo.bar
# This way both the origional definition in this Makefile and your own are
# used.
#
# Changes:
# - March 22, 1999:
# Added -o $@ to the dvips invocation.
# - June 3, 1999:
# Removed the target "all" from the help output.
# - June 4, 1999:
# 'latexclean' now only removes a DVI files if there is a TeX file
# with the same name.
# - June 17, 1999:
# Removed the `find' command in the latexclean target. This is because
# the option '-maxdepth' is Linux-specific. And `ls' is simpler anyway.
# :-)
# - July 15, 1999:
# The variables "LATEX", "BIBTEX", etc. are now taken from the environment
# if they are defined there.
#.SILENT:
SHELL=/bin/bash
ifndef LATEX
LATEX=latex
endif
ifndef BIBTEX
BIBTEX=bibtex
endif
ifndef DVIPS
DVIPS=dvips
endif
ifndef MAKEINDEX
MAKEINDEX=makeindex
endif
ifndef DVIVIEWER
DVIVIEWER=xdvi
endif
ifndef LATEX2HTML
LATEX2HTML=latex2html
endif
ifndef SED
SED=sed
endif
ifndef PDFLATEX
PDFLATEX=pdflatex
endif
ifndef THUMBPDF
THUMBPDF=thumbpdf
endif
FIGURES=$(wildcard *.fig)
FIGUREOBJS=$(FIGURES:.fig=.eps)
TEXFILES=$(wildcard *.tex)
#test: latexhelp
# Disable standard pattern rule:
%.dvi: %.tex
# Do not delete the following targets:
.PRECIOUS: %.aux %.bbl %.eps %.ind
%.aux: %.tex $(FIGUREOBJS) $(TEXFILES)
@$(LATEX) $*
# Look for citations. Make sure grep never returns an error code.
@grep "^\\\\citation" *.aux > .btmp.new || true
# If the citations are not changed, don't do anything. Otherwise replace
# the .btmp file to make sure Bibtex will be run.
@if ( diff .btmp.new .btmp >& /dev/null ); then \
rm .btmp.new; \
else \
mv .btmp.new .btmp; \
fi
@if [ -f $*.idx ]; then cp $*.idx .itmp.new; else touch .itmp.new; fi
@if ( diff .itmp.new .itmp >& /dev/null ); then \
rm .itmp.new; \
else \
mv .itmp.new .itmp; \
fi
.btmp:
%.bbl: $(BIBFILES) .btmp
# Only use BibTeX if \bibliography occurs in the document. In that case,
# run BibTeX and recompile. .btmp is touched to prevent useless making
# next time.
@if ( grep "^\\\\bibliography{" $*.tex > /dev/null ); then \
$(BIBTEX) $*; \
touch .rerun; \
fi
@touch .btmp
.itmp:
%.ind: .itmp
@if [ -f $*.idx ]; then \
cat $*.idx | $(SED) -e 's/ *{/{/g;s/ *}/}/g;s/ *=/=/g' > temp.idx; \
rm $*.idx; \
mv temp.idx $*.idx; \
$(MAKEINDEX) -g -s rene.ist $*; \
touch .rerun; \
touch .itmp; \
fi
%.eps:%.fig
@echo Generating figure $@...
@fig2dev -L ps $< $@
%.dvi: %.aux %.ind %.bbl
# Make sure the dvi-file exists; if not: recompile.
@if [ ! -f $*.dvi ]; then \
touch .rerun; \
fi
@if [ -f .rerun ]; then \
rm .rerun; \
$(LATEX) $*; \
else \
$(MAKE) $*.aux; \
fi
# While references et al. are changed: recompile.
@while ( grep Rerun $*.log > /dev/null ); do \
$(LATEX) $*; \
done
# Touch the figureobjects to prevent making next time
@if [ -n "$(FIGUREOBJS)" ]; then \
touch $(FIGUREOBJS); \
touch $*.aux; \
fi
@if [ -f $*.ind ]; then \
touch $*.ind; \
fi
%.pdf: %.aux %.ind %.bbl
# Make sure the pdf-file exists; if not: recompile.
@if [ ! -f $*.pdf ]; then \
touch .rerun; \
fi
@if [ -f .rerun ]; then \
rm .rerun; \
$(PDFLATEX) $*; \
$(THUMBPDF) $*; \
$(PDFLATEX) $*; \
else \
$(MAKE) $*.aux; \
fi
# While references et al. are changed: recompile.
@while ( grep Rerun $*.log > /dev/null ); do \
$(PDFLATEX) $*; \
$(THUMBPDF) $*; \
$(PDFLATEX) $*; \
done
# Touch the figureobjects to prevent making next time
@if [ -n "$(FIGUREOBJS)" ]; then \
touch $(FIGUREOBJS); \
touch $*.aux; \
fi
@if [ -f $*.ind ]; then \
touch $*.ind; \
fi
latex:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.dvi; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.dvi; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.dvi; \
true; \
fi; \
fi
pdflatex:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.pdf; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.pdf; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
true; \
fi; \
fi
latexfigures:
@for i in $(FIGUREOBJS); do \
$(MAKE) $$i; \
done
view:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.dvi && \
$(DVIVIEWER) ${LATEXTARGET}.dvi; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.dvi && \
$(DVIVIEWER) `basename \`ls *.tex\` .tex`.dvi; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.dvi && \
$(DVIVIEWER) `echo $$PWD|tr '/' '\n'|tail -1`.dvi; \
true; \
fi; \
fi
%.ps: %.dvi
$(DVIPS) -o $@ $<
latexps:
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.ps && \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.ps && \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.ps && \
true; \
fi; \
fi
html: .html
.html:
@if [ -n "${LATEXTARGET}" ]; then \
if [ -n "${HTMLDIR}" ]; then \
$(MAKE) ${LATEXTARGET}.dvi; \
$(LATEX2HTML) $(LATEX2HTML_OPTS) -dir $(HTMLDIR)/$(LATEXTARGET) $(LATEXTARGET) && \
chmod a+rx $(HTMLDIR)/$(LATEXTARGET) && \
chmod a+r $(HTMLDIR)/$(LATEXTARGET)/* && \
touch .html; \
else \
echo Set variable HTMLDIR\!; \
fi; \
else \
echo Set variable LATEXTARGET\!; \
fi
latexhelp:
@echo "LaTeX Makefile Options"
@echo "----------------------"
@echo ""
@echo "Environment variables:"
@echo " LATEXTARGET Filename to make (without extension)"
@echo " HTMLDIR Directory for HTML-output"
@echo " FIGURES Figures that have to be compiled"
@echo ""
@echo "Targets:"
@echo " <name>.dvi Make the given dvi file"
@echo " latex Make the LATEXTARGET or <dirname>.dvi"
@echo " pdflatex Make the LATEXTARGET or <dirname>.pdf"
@echo " latexps Make the LATEXTARGET or <dirname>.ps"
@echo " view Make and view the LATEXTARGET or <dirname>.dvi"
@echo " html Make the LATEXTARGET or <dirname>.dvi and generate HTML output"
@echo " latexhelp This overview"
@echo " latexclean Remove all generated files"
latexclean::
@rm -f *.log *.aux *.bbl *.blg *.ilg *.toc *.lof *.lot *.idx *.ind .html .btmp .itmp .rerun *~
@rm -f thumb[0-9][0-9][0-9].png
@rm -f thumbdta.tex thumbpdf.pdf
@for i in *.eps; do \
if [ -f "`basename $$i .eps`.fig" ]; then \
rm -f $$i; \
elif ( rcs `basename $$i .eps`.fig >& /dev/null ); then \
rm -f $$i; \
fi \
done
@for i in *.dvi; do \
if [ -f "`basename $$i .dvi`.tex" ]; then \
rm -f $$i; \
fi \
done
@for i in *.pdf; do \
if [ -f "`basename $$i .pdf`.tex" ]; then \
rm -f $$i; \
fi \
done

324
beispiele.tex Normal file
View File

@ -0,0 +1,324 @@
\chapter{Beispiele}
\section{Schleifen und Rückgabewerte}\label{beisp_schleifen_exitcode}\index{Schleife}\index{Rückgabewert}
Man kann mit einer \texttt{until}\index{until=\texttt{until}}- bzw. mit einer \texttt{while}\index{while=\texttt{while}}-Schleife schnell kleine aber sehr nützliche Tools schreiben, die einem lästige Aufgaben abnehmen.
\subsection{Schleife, bis ein Kommando erfolgreich war}
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 \texttt{who}\index{who=\texttt{who}} ausführen, und dann in der Ausgabe nach dem Eintrag `\texttt{root}' suchen. Das ist aber lästig.
Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30 Sekunden automatisch überprüft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code:
\footnotesize
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
\begin{listing}[2]{1}
#!/bin/sh
until who | grep "^root "
do sleep 30
done
echo Big Brother is watching you!
\end{listing}
\normalsize
Das Skript führt also so lange das Kommando aus, bis die Ausführung erfolgreich war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am Zeilenanfang. Der Rückgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist 0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze Zeit mit dieser Schleife beschäftigt ist, wird im Schleifenkörper ein \texttt{sleep 30}\index{sleep=\texttt{sleep}} ausgeführt, um den Prozeß für 30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird eine entsprechende Meldung ausgegeben.
\subsection{Schleife, bis ein Kommando erfolglos war}
Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die \texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife:
\footnotesize
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
\begin{listing}[2]{1}
#!/bin/sh
while who | grep "^root "
do sleep 30
done
echo Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!
\end{listing}
\normalsize
Die Schleife wird nämlich dann so lange ausgeführt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zurückmeldet.
\section{Eine Datei zeilenweise bearbeiten}
\texttt{cat datei.txt | while read i}
TODO!!!
Achtung! while ist eine Subshell - Daten müssen hochgereicht werden.
\section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript}
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird während des Bootvorgangs gestartet, wenn der dazugehörige Runlevel initialisiert wird.
Das Skript muß mit einem Parameter\index{Parameter} aufgerufen werden. Möglich sind hier \textsl{start}, \textsl{stop}, \textsl{status}, \textsl{restart} und \textsl{reload}. Wenn falsche Parameter\index{Parameter} übergeben wurden, wird eine entsprechende Meldung angezeigt.
Das Ergebnis der Ausführung wird mit Funktionen\index{Funktion} dargestellt, die aus der Datei \texttt{/etc/rc.d/init.d/functions} stammen. Ebenfalls in dieser Datei sind Funktionen, die einen Dienst starten oder stoppen.
\begin{flushright}
Zunächst wird festgelegt, daß dieses Skript in der Bourne-Shell ausgeführt werden soll (\ref{auswahl_der_shell}).
\end{flushright}
\footnotesize
\begin{listing}[2]{1}
#!/bin/sh
\end{listing}
\normalsize
\begin{flushright}
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erläutern (\ref{kommentare}).
\end{flushright}
\footnotesize
\begin{listingcont}
#
# 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{listingcont}
\normalsize
\begin{flushright}
Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}).
\end{flushright}
\footnotesize
\index{source=\texttt{source}}
\begin{listingcont}
# Source function library.
. /etc/rc.d/init.d/functions
\end{listingcont}
\normalsize
\begin{flushright}
Hier werden die Aufrufparameter ausgewertet (\ref{case}).
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}
\begin{listingcont}
# See how we were called.
case "$1" in
start)
echo -n "Starting httpd: "
\end{listingcont}
\normalsize
\begin{flushright}
Nachdem eine Meldung über den auszuführenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgeführt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} übergeben wird. Dann gibt sie eine Meldung über den Erfolg aus.
\end{flushright}
\footnotesize
\begin{listingcont}
daemon httpd
echo
\end{listingcont}
\normalsize
\begin{flushright}
Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, daß ein bestimmter Prozeß bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt.
\end{flushright}
\footnotesize
\index{Anführungszeichen}\index{touch=\texttt{touch}}
\begin{listingcont}
touch /var/lock/subsys/httpd
;;
stop)
echo -n "Shutting down http: "
\end{listingcont}
\normalsize
\begin{flushright}
Hier passiert im Prinzip das gleiche wie oben, nur daß mit der Funktion \texttt{killproc} der Daemon angehalten wird.
\end{flushright}
\footnotesize
\begin{listingcont}
killproc httpd
echo
\end{listingcont}
\normalsize
\begin{flushright}
Danach werden Lock-File und PID-File\footnote{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).} gelöscht.
\end{flushright}
\footnotesize
\begin{listingcont}
rm -f /var/lock/subsys/httpd
rm -f /var/run/httpd.pid
;;
status)
\end{listingcont}
\normalsize
\begin{flushright}
Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits läuft, und gibt das Ergebnis aus.
\end{flushright}
\footnotesize
\begin{listingcont}
status httpd
;;
restart)
\end{listingcont}
\normalsize
\begin{flushright}
Bei Aufruf mit dem Parameter\index{Parameter} \textsl{restart} ruft sich das Skript zwei mal selbst auf (in \texttt{\$0} steht der Aufrufname des laufenden Programms). Einmal, um den Daemon zu stoppen, dann, um ihn wieder zu starten.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}
\begin{listingcont}
$0 stop
$0 start
;;
reload)
echo -n "Reloading httpd: "
\end{listingcont}
\normalsize
\begin{flushright}
Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, daß er seine Konfiguration neu einlesen soll.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}
\begin{listingcont}
killproc httpd -HUP
echo
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status}"
\end{listingcont}
\normalsize
\begin{flushright}
Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird dafür gesorgt, daß das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgemäß beendet wurde (\ref{exit}).
\end{flushright}
\footnotesize
\index{exit=\texttt{exit}}
\begin{listingcont}
exit 1
esac
exit 0
\end{listingcont}
\normalsize
\section{Parameterübergabe in der Praxis}\label{beisp_parameter}\index{Parameter}
Es kommt in der Praxis sehr oft vor, daß man ein Skript schreibt, dem derAnwender Parameter\index{Parameter} übergeben soll. Wenn das nur eine Kleinigkeit ist (zum Beispiel ein Dateiname), dann fragt man einfach die entsprechenden vordefinierten Variablen (\ref{vordefinierte_variablen}) ab. Sollen aber `richtige' Parameter\index{Parameter} eingesetzt werden, die sich so einsetzen lassen wie man es von vielen Kommandozeilentools gewohnt ist, dann benutzt man das Hilfsprogramm \texttt{getopt}\label{getopt}\index{getopt=\texttt{getopt}}. Dieses Programm parst die originalen Parameter\index{Parameter} und gibt sie in `standardisierter' Form zurück.
Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die Optionen \texttt{-a} und \texttt{-b}. Letzterer Option muß ein zusätzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert.
\footnotesize
\index{\$@=\texttt{\$@}}\index{Anführungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}}
\begin{listing}[2]{1}
#!/bin/sh
set -- `getopt "ab:" "$@"` || {
\end{listing}
\normalsize
\begin{flushright}
Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so daß es aussieht, als ob dem Skript die Rückgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} übergeben wurden. Man muß die beiden Minuszeichen angeben, da sie dafür sorgen, daß die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst übergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zurückgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der Möglichkeit einer zusätzlichen Angabe.
Wenn dieses Kommando fehlschlägt ist das ein Zeichen dafür, daß falsche Parameter\index{Parameter} übergeben wurden. Also wird nach einer entsprechenden Meldung das Programm mit Exit-Code 1 verlassen.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Null-Befehl}\index{!>\&=\texttt{!>\&}}\index{!==\texttt{!=}}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{listingcont}
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{listingcont}
\normalsize
\begin{flushright}
In einer Endlosschleife\index{Endlosschleife}, die man mit Hilfe des Null-Befehls (\texttt{:}, \ref{null-befehl}) baut, werden die `neuen' Parameter\index{Parameter} der Reihe nach untersucht. Wenn ein \texttt{-a} vorkommt, wird die Variable \texttt{aflag} gesetzt. Bei einem \texttt{-b} werden per \texttt{shift}\index{shift=\texttt{shift}} alle Parameter\index{Parameter} nach Links verschoben, dann wird der Inhalt des nächsten Parameters\index{Parameter} in der Variablen \texttt{name} gesichert.
\end{flushright}
\footnotesize
\index{!==\texttt{!=}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}}
\begin{listingcont}
case "$1" in
-a) aflag=1 ;;
-b) shift; name="$1" ;;
--) break ;;
\end{listingcont}
\normalsize
\begin{flushright}
Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, daß die Liste der Parameter\index{Parameter} abgearbeitet ist. Dann wird per \texttt{break}\index{break=\texttt{break}} (\ref{break}) die Endlosschleife unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell angegebenen Dateinamen, die jetzt von dem Restlichen Skript wie gewohnt weiterverarbeitet werden können.
\end{flushright}
\footnotesize
\index{shift=\texttt{shift}}
\begin{listingcont}
esac
shift
done
shift
\end{listingcont}
\normalsize
\begin{flushright}
Am Ende werden die Feststellungen ausgegeben.
\end{flushright}
\footnotesize
\index{\$*=\texttt{\$*}}\index{Anführungszeichen}
\begin{listingcont}
echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
\end{listingcont}
\normalsize
\section{Fallensteller: Auf Traps
reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(}
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste (normalerweise \Ovalbox{CTRL}-\Ovalbox{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 bestimmte Aufgaben auf jeden Fall erledigen muß, bevor es sich beendet.
Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle sind in der Man-Page von \texttt{signal} beschrieben. Hier die wichtigsten:\nopagebreak
\LTXtable{\textwidth}{tab_signale.tex}
Wie löst man jetzt dieses Problem? Glücklicherweise verfügt die Shell über das \texttt{trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann. Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein temporäres File entpacken, dieses mit \texttt{pg} seitenweise anzeigen und nachher wieder löschen.
\footnotesize
\index{!==\texttt{!=}}
\begin{listing}[2]{1}
#!/bin/sh
stat=1
temp=/tmp/zeige$$
\end{listing}
\normalsize
\begin{flushright}
Zunächst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines Abbruchs als Exit-Status zurückliefern soll. Die Variable \texttt{temp} enthält den Namen für eine temporäre Datei. Dieser setzt sich zusammen aus \texttt{/tmp/zeige} und der Prozeßnummer des laufenden Skripts. So soll sichergestellt werden, daß noch keine Datei mit diesem Namen existiert.
\end{flushright}
\footnotesize
\index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{listingcont}
trap 'rm -f $temp; exit $stat' 0
trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15
\end{listingcont}
\normalsize
\begin{flushright}
Hier werden die Traps definiert. Bei Signal 0 wird die temporäre Datei gelöscht und der Wert aus der Variable \texttt{stat} als Exit-Code zurückgegeben. Dabei wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-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 Kill\index{kill=\texttt{kill}}. Der zweite Trap reagiert auf die Signale 1, 2 und 15. Das heißt, er wird bei jedem unnormalen Ende ausgeführt. Er gibt eine entsprechende Meldung auf die Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet, und der erste Trap wird ausgeführt.
\end{flushright}
\footnotesize
\index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}
\begin{listingcont}
case $# in
1) zcat "$1" > $temp
pg $temp
stat=0
;;
\end{listingcont}
\normalsize
\begin{flushright}
Jetzt kommt die eigentliche Funktionalität des Skriptes: Das \texttt{case}-Kommando (\ref{case}) testet die Anzahl der übergebenen Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} übergeben wurde, entpackt \texttt{zcat} die Datei, die im ersten Parameter\index{Parameter} angegeben wurde, in die temporäre Datei. Dann folgt die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte Exit-Code zurückgegeben wird.
\end{flushright}
\footnotesize
\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{listingcont}
*) echo "Anwendung: `basename $0` Dateiname" 1>&2
esac
\end{listingcont}
\normalsize
\begin{flushright}
Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
\end{flushright}
\index{trap=\texttt{trap}|)}\index{Signal|)}

10
quellen.tex Normal file
View File

@ -0,0 +1,10 @@
\chapter{Quellen}
\begin{itemize}
\item Bash Reference Manual (\texttt{http://www.gnu.org/manual/bash-2.02/\\bashref.html})
\item Unix In A Nutshell (\texttt{http://www.oreilly.com/catalog/unixnut3/})
\item Unix Power Tools (\texttt{http://www.oreilly.com/catalog/upt2/})
\item Von DOS nach Linux HOWTO (\texttt{http://www.tu-harburg.de/\\\~{}semb2204/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
\item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das
kann ich nur jedem empfehlen - es ist spannender als es sich anhört...).
\end{itemize}

34
rene.ist Normal file
View File

@ -0,0 +1,34 @@
% [rene.ist] 23.02.97 R.Scholz <mrz@informatik.uni-jena.de>
%
% Style-Datei für makeindex.
% Aufruf: makeindex [-c] -g -s rene[.ist] tex-file
actual '=' % = statt @
quote '!' % ! statt "
level '>' % > statt !
preamble
"\n \\begin{theindex}\n"
postamble
"\n\n \\end{theindex}\n"
item_x1 "\\hspace{\\stretch{2}} \n \\subitem "
item_x2 "\\hspace{\\stretch{2}} \n \\subsubitem "
delim_0 "\\dotfill "
delim_1 "\\dotfill "
delim_2 "\\dotfill "
suffix_2p "f."
suffix_3p "ff."
% The next lines will produce some warnings when
% running Makeindex as they try to cover two different
% versions of the program:
%lethead_prefix "{\\bfseries\\hfil "
%lethead_suffix "\\hfil}\\nopagebreak\n"
%lethead_flag 0
heading_prefix "{\\bfseries\\hfil " % vor Buchstabe einfügen
heading_suffix "\\hfil}\\nopagebreak\n" % nach Buchstabe einfügen
headings_flag 1 % Überschriften ein (Großbuchstaben)
symhead_positive "Symbole"
numhead_positive "Zahlen"

51
schmutzige_tricks.tex Normal file
View File

@ -0,0 +1,51 @@
\chapter{Schmutzige Tricks :-)}
Eigentlich sind diese Tricks gar nicht so schmutzig. Hier ist lediglich eine
Sammlung von Beispielen, die genial einfach oder genial gut programmiert sind.
Das bedeutet nicht, daß jeder Shell-Programmierer diese Techniken benutzen
sollte. Ganz im Gegenteil. Einige Mechanismen bergen Gefahren, die nicht auf
den ersten Blick erkennbar sind.
Mit anderen Worten: \textbf{Wenn Du diese Techniken nicht verstehst, dann
benutze sie nicht!}
Die Intention hinter diesem Abschnitt ist es, dem gelangweilten Skripter etwas
interessantes zum Lesen zu geben. Das inspiriert dann vielleicht dazu, doch
einmal in den fortgeschrittenen Bereich vorzustoßen, neue Techniken
kennenzulernen. Außerdem kann das Wissen über gewisse Techniken eine große
Hilfe beim Lesen fremder Skripte darstellen, die eventuell von diesen Techniken
Gebrauch machen.
Diese Techniken sind nicht `auf meinem Mist gewachsen', sie stammen vielmehr
aus Skripten, die mir im Laufe der Zeit in die Finger gekommen sind. Ich danke
an dieser Stelle den klugen Köpfen, die sich solche Sachen einfallen lassen
haben.
\section{Die Tar-Brücke}
TODO!!!
\section{Binaries inside}
TODO!!!
\subsection{Binäre Here-Dokumente}
TODO!!!
\subsection{Schwanz ab!}
TODO!!!
\section{Dateien, die es nicht gibt}
TODO!!!
\subsection{Speichern in nicht existente Dateien}
TODO!!!
\subsection{Daten aus einer Subshell hochreichen}
TODO!!!

156
shell.tex Normal file
View File

@ -0,0 +1,156 @@
%==============================================================================
% LaTeX-Schema-Datei schema.tex
%==============================================================================
%==============================================================================
% Vorspann
%==============================================================================
\newif\ifpdf % Feststellen, ob wir PDF oder DVI
% erzeugen
\ifx\pdfoutput\undefined
\pdffalse % Wir haben kein PDFLaTeX
\else
\pdftrue % Wir haben PDFLaTeX
\fi
\ifpdf % PDF-Einstellungen
\pdfoutput=1
\pdfcompresslevel=9
\pdfinfo{
/Author (Ronald Schaten)
/CreationDate (D:20000301170300) % (D:YYYYMMDDhhmmss)
% /ModDate (D:19980212201000) % ModDate is similar
/Title (Shell-Programmierung)
/Subject (Shell-Programmierung)
/Keywords (Shell)
}
\pdfcatalog{ % Catalog dictionary of PDF output.
/PageMode /UseOutlines
/URI (http://www.fi.muni.cz/)
}
\else % Nicht-PDF-Einstellungen
\fi
% Dokumentstil für Buch
\documentclass[a4paper,12pt,draft,twoside]{book}
\usepackage{german} % deutsches Paket für Umlaute
%\usepackage{t1enc} % DC-Font mit 8 Bit verwenden
\usepackage[latin1]{inputenc} % Codepage latin1
%\usepackage{graphicx} % Grafikpaket für Bilder laden
%\DeclareGraphicsRule{.tif}{bmp}{}{} % Grafikformate
\usepackage{tabularx} % für Tabellen über die Seitenbreite
\usepackage{longtable} % für Tabellen über die Seitenbreite
\usepackage{supertabular} % für Tabellen über die Seitenbreite
\usepackage{ltxtable} % für Tabellen über die Seitenbreite
\ifpdf % PDF-Einstellungen
\usepackage{thumbpdf}
\else % Nicht-PDF-Einstellungen
\fi
\usepackage{makeidx} % Index wird später eingefügt
\makeindex % durch \printindex
\usepackage{tocbibind} % TOC, Index etc. kommt in die TOC
\usepackage{fancybox} % Kästchen für Tastendarstellung
\usepackage{fancyhdr} % Kopf- und Fußzeilen
\pagestyle{fancy}
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
\fancyhf{}
\fancyhead[RE]{\bfseries\leftmark}
\fancyhead[LO]{\bfseries\rightmark}
\fancyhead[RO,LE]{\bfseries\thepage}
\renewcommand{\headrulewidth}{0.5pt}
\addtolength{\headheight}{2.5pt}
\fancypagestyle{plain}{
\fancyhead{}
\renewcommand{\headrulewidth}{0pt}
\fancyfoot[C]{\bfseries\thepage}
}
\usepackage{moreverb} % Für Listings
\newcommand{\STRUT}{\rule{0in}{3ex}} % Ein vertikaler Abstand für Tabellen
\clubpenalty=10000 % gegen Schusterjungen
\widowpenalty=10000 % gegen Hurenkinder
%==============================================================================
% Anfang des Dokuments
%==============================================================================
\begin{document} % hiermit muß jedes Dokument beginnen
\vspace*{.75in} % Die Titelseite
\thispagestyle{empty}
\begin{centering}
\rule{5in}{.04in}\\ \vspace{.25in}
\Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in}
\rule{5in}{.04in}\\ \vspace{.5in}
\large \today\\ \vspace{.75in}
\large von\\ \vspace{.3in}
\LARGE {\bf Ronald Schaten} \\ \vspace{.6in}
\large ronald@schatenseite.de\\
\large http://www.schatenseite.de/\\
\end{centering}
\newpage
\thispagestyle{empty} % eine Leerseite
~\vfill
\footnotesize
Copyright \copyright{} 2001 Ronald Schaten (\texttt{ronald@schatenseite.de})\bigskip
Die aktuellste Version dieses Dokumentes befindet sich im World Wide Web auf meiner Homepage (\texttt{http://www.schatenseite.de/}).\bigskip
Dieses Dokument ist entstanden, weil ich für mich selbst eine kompakte Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verfügung, in der Hoffnung, daß andere Leute daraus vielleicht einen Nutzen ziehen können. \textbf{Aber ich übernehme keine Garantie für die Korrektheit der hier dargestellten Dinge.} Mit der Formulierung \textsl{'daraus vielleicht einen Nutzen ziehen können'} meine ich nicht, daß dieses Dokument~---~oder Teile daraus~---~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos weitergegeben werden.}\bigskip
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in chronologischer Reihenfolge ihres Eingreifens):
\begin{list}{$\bullet$}{\itemsep=-0.5cm}
\item Jürgen Ilse (\texttt{ilse@asys-h.de})\\
\item Christian Perle (\texttt{christian.perle@tu-clausthal.de})\\
\item Andreas Metzler (\texttt{ametzler@downhill.at.eu.org})\\
\item Johannes Kolb (\texttt{johannes.kolb@web.de})\\
\end{list}
Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf aufmerksam zu machen. Auch abgesehen davon freue ich mich über jede Rückmeldung.
\normalsize
\newpage
\pagenumbering{roman}
\renewcommand{\headrulewidth}{0.5pt}
\setcounter{tocdepth}{3}
\tableofcontents
\newpage
\pagenumbering{arabic}
% Haupttextteil
\include{was_ist_die_shell}
\include{wofuer_shell_programmierung}
\include{wie_sieht_ein_shell_skript_aus}
\include{nuetzliche_shell-kommandos}
\include{wo_sind_unterschiede_zu_dos_batchdateien}
\appendix
\include{beispiele}
\include{schmutzige_tricks}
\include{quellen}
\printindex % Index einfügen
%==============================================================================
% Ende des Dokuments
%==============================================================================
\end{document}
\ifpdf % PDF-Einstellungen
\bye
\else % Nicht-PDF-Einstellungen
\fi
%==============================================================================
% Ende von schema.tex
%==============================================================================

View File

@ -0,0 +1,24 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-b }\textsl{Datei} & Die \textsl{Datei} existiert und ist ein blockorientiertes Gerät \tabularnewline\STRUT
\texttt{-c }\textsl{Datei} & Die \textsl{Datei} existiert und ist ein zeichenorientiertes Gerät \tabularnewline\STRUT
\texttt{-d }\textsl{Datei} & Die \textsl{Datei} existiert und ist ein Verzeichnis \tabularnewline\STRUT
\texttt{-f }\textsl{Datei} & Die \textsl{Datei} existiert und ist eine reguläre Datei \tabularnewline\STRUT
\texttt{-g }\textsl{Datei} & Die \textsl{Datei} existiert, und das Gruppen-ID-Bit\index{Gruppen-ID-Bit} ist gesetzt \tabularnewline\STRUT
\texttt{-h }\textsl{Datei} & Die \textsl{Datei} existiert und ist ein symbolischer Link\index{Link} \tabularnewline\STRUT
\texttt{-k }\textsl{Datei} & Die \textsl{Datei} existiert, und das Sticky-Bit\index{Sticky-Bit} ist gesetzt \tabularnewline\STRUT
\texttt{-p }\textsl{Datei} & Die \textsl{Datei} existiert und ist eine Named Pipe \tabularnewline\STRUT
\texttt{-r }\textsl{Datei} & Die \textsl{Datei} existiert und ist lesbar \tabularnewline\STRUT
\texttt{-s }\textsl{Datei} & Die \textsl{Datei} existiert und ist nicht leer \tabularnewline\STRUT
\texttt{-t }\textsl{[n]} & Der offene Dateideskriptor\index{Dateideskriptor} \textsl{n} gehört zu einem Terminal; Vorgabe für \textsl{n} ist 1. \tabularnewline\STRUT
\texttt{-u }\textsl{Datei} & Die \textsl{Datei} existiert und das Setuid-Bit\index{Setuid-Bit} ist gesetzt \tabularnewline\STRUT
\texttt{-w }\textsl{Datei} & Die \textsl{Datei} existiert und ist beschreibbar \tabularnewline\STRUT
\texttt{-x }\textsl{Datei} & Die \textsl{Datei} existiert und ist ausführbar
\end{longtable}

View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{n1}\texttt{ -eq }\textsl{n2} & \textsl{n1} ist gleich \textsl{n2} \tabularnewline\STRUT
\textsl{n1}\texttt{ -ge }\textsl{n2} & \textsl{n1} ist größer oder gleich \textsl{n2} \tabularnewline\STRUT
\textsl{n1}\texttt{ -gt }\textsl{n2} & \textsl{n1} ist größer als \textsl{n2} \tabularnewline\STRUT
\textsl{n1}\texttt{ -le }\textsl{n2} & \textsl{n1} ist kleiner oder gleich \textsl{n2} \tabularnewline\STRUT
\textsl{n1}\texttt{ -lt }\textsl{n2} & \textsl{n1} ist kleiner \textsl{n2} \tabularnewline\STRUT
\textsl{n1}\texttt{ -ne }\textsl{n2} & \textsl{n1} ist ungleich \textsl{n2}
\end{longtable}

View File

@ -0,0 +1,14 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{(}\textsl{Bedingung}\texttt{)}\index{( )=\texttt{( )}|textbf} & Wahr, wenn die \textsl{Bedingung} zutrifft (wird für die Gruppierung verwendet). Den Klammern muß ein \texttt{\textbackslash} vorangestellt werden. \tabularnewline\STRUT
\texttt{! }\textsl{Bedingung}\index{!!=\texttt{!!}|textbf} & Wahr, wenn die \textsl{Bedingung} nicht zutrifft (NOT\index{NOT}\index{Negation|see{NOT}}). \tabularnewline\STRUT
\textsl{Bedingung1}\texttt{ -a }\textsl{Bedingung2} & Wahr, wenn beide Bedingungen zutreffen (AND\index{AND}\index{Und-Verknüpfung|see{AND}}). \tabularnewline\STRUT
\textsl{Bedingung1}\texttt{ -o }\textsl{Bedingung2} & Wahr, wenn eine der beiden Bedingungen zutrifft (OR\index{OR}\index{Oder-Verknüpfung|see{OR}}).
\end{longtable}

View File

@ -0,0 +1,15 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-n }\textsl{s1} & Die Länge der Zeichenfolge \textsl{s1} ist ungleich Null \tabularnewline\STRUT
\texttt{-z }\textsl{s1} & Die Länge der Zeichenfolge \textsl{s1} ist gleich Null \tabularnewline\STRUT
\textsl{s1}\texttt{ = }\textsl{s2}\index{!==\texttt{!=}} & Die Zeichenfolgen \textsl{s1} und \textsl{s2} sind identisch \tabularnewline\STRUT
\textsl{s1}\texttt{ != }\textsl{s2}\index{!!!==\texttt{!!!=}|textbf} & Die Zeichenfolgen \textsl{s1} und \textsl{s2} sind \textsl{nicht} identisch \tabularnewline\STRUT
\textsl{Zeichenfolge} & Die \textsl{Zeichenfolge} ist nicht Null
\end{longtable}

18
tab_befehlsformen.tex Normal file
View File

@ -0,0 +1,18 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{Befehl}\texttt{ \&} & Ausführung von \textsl{Befehl} im Hintergrund \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2} & Befehlsfolge, führt mehrere Befehle nacheinander aus \tabularnewline\STRUT
\texttt{(}\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{)} & Subshell\index{Subshell}, behandelt \textsl{Befehl1} und \textsl{Befehl2} als Befehlsblock und führt sie in einer Subshell aus \tabularnewline\STRUT
\texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{ \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgeführt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgeführt würde \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ | }\textsl{Befehl2} & Pipe\index{Pipe}, verwendet die Ausgabe von \textsl{Befehl1} als Eingabe für \textsl{Befehl2} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ `}\textsl{Befehl2}\texttt{`} & Befehls-Substitution, verwendet die Ausgabe von \textsl{Befehl2} als Argumente\index{Parameter}\index{Argument|see{Parameter}} für \textsl{Befehl1} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ \&\& }\textsl{Befehl2} & AND\index{AND}, führt zuerst \textsl{Befehl1} und dann (wenn \textsl{Befehl1} erfolgreich war) \textsl{Befehl2} aus\footnote{Einen ähnlichen Mechanismus kennt man aus verschiedenen Programmiersprachen unter dem Begriff \textsl{Kurzschlußauswertung}\index{Kurzschlußauswertung} bzw. \textsl{lazy evaluation}\index{Lazy Evaluation|see{Kurzschlußauswertung}}.} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ || }\textsl{Befehl2} & OR\index{OR}, entweder \textsl{Befehl1} ausführen oder \textsl{Befehl2} (Wenn \textsl{Befehl1} nicht erfolgreich war)
\end{longtable}

16
tab_beisp_bedingungen.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{while test \$\# -gt 0}\index{\$\#=\texttt{\$\#}} & Solange Argumente\index{Parameter} vorliegen\ldots \tabularnewline\STRUT
\texttt{while [ -n \dq\$1\dq~]}\index{\$n=\texttt{\$}$n$} & Solange das erste Argument\index{Parameter} nicht leer ist\ldots\index{Anführungszeichen} \tabularnewline\STRUT
\texttt{if [ \$count -lt 10 ]} & Wenn \texttt{\$count} kleiner 10\ldots \tabularnewline\STRUT
\texttt{if [ -d RCS ]} & Wenn ein Verzeichnis RCS existiert\ldots \tabularnewline\STRUT
\texttt{if [ \dq\$Antwort\dq~!= \dq j\dq~]}\index{!!!==\texttt{!!!=}} & Wenn die Antwort nicht \dq j\dq~ ist\ldots\index{Anführungszeichen} \tabularnewline\STRUT
\texttt{if [ ! -r \dq\$1\dq~-o ! -f \dq\$1\dq~]}\index{!!=\texttt{!!}}\index{\$n=\texttt{\$}$n$} & Wenn das erste Argument\index{Parameter} keine lesbare oder reguläre Datei ist\ldots\index{Anführungszeichen}
\end{longtable}

View File

@ -0,0 +1,18 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ nroff }\textsl{Datei}\texttt{ \&} & Formatiert die \textsl{Datei} im Hintergrund \tabularnewline\STRUT
\texttt{\$ cd; ls} & Sequentieller Ablauf \tabularnewline\STRUT
\texttt{\$ (date; who; pwd) > logfile}\index{!>=\texttt{!>}} & Führt die Befehle in einer Subshell\index{Subshell} aus und lenkt alle Ausgaben um \tabularnewline\STRUT
\texttt{\$ \{ date; who; pwd \} > logfile}\index{!>=\texttt{!>}} & Lenkt alle Ausgaben um \tabularnewline\STRUT
\texttt{\$ sort }\textsl{Datei}\texttt{ | lp} & Sortiert die \textsl{Datei} und druckt sie\index{sort=\texttt{sort}} \tabularnewline\STRUT
\texttt{\$ vi `grep -l ifdef *.c`}\index{*=\texttt{*}}\index{grep=\texttt{grep}} & Editiert die mittels grep gefundenen Dateien \tabularnewline\STRUT
\texttt{\$ grep }\textsl{XX Datei}\texttt{ \&\& lp }\textsl{Datei}\index{grep=\texttt{grep}} & Druckt die \textsl{Datei}, wenn sie \textsl{XX} enthält\index{AND} \tabularnewline\STRUT
\texttt{\$ grep }\textsl{XX Datei}\texttt{ || lp }\textsl{Datei}\index{grep=\texttt{grep}} & Druckt die \textsl{Datei}, wenn sie \textsl{XX} nicht enthält\index{OR}
\end{longtable}

27
tab_beisp_case.tex Normal file
View File

@ -0,0 +1,27 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Mit dem ersten Argument\index{Parameter} in der Befehlszeile wird die entsprechende Aktion festgelegt:}} \\
\multicolumn{2}{|X|}{\texttt{case \$1 in~~\# nimmt das erste Argument}\index{\$n=\texttt{\$}$n$}} \\
\multicolumn{2}{|X|}{\texttt{~Ja|Nein) response=1;;}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\texttt{~~~-[tT]) table=TRUE;;}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~*) echo \dq Unbekannte Option\dq; exit 1;;}} \\
\multicolumn{2}{|X|}{\texttt{esac}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Lies die Zeilen von der Standard-Eingabe\index{Standard-Eingabe}, bis eine Zeile mit einem einzelnen Punkt eingegeben wird:}} \\
\multicolumn{2}{|X|}{\texttt{while :~~\# Null-Befehl (immer wahr, siehe unter \ref{null-befehl})}\index{Null-Befehl}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Zum Beenden . eingeben ==> \textbackslash c\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~read line~~\# read: Zeile von StdIn einlesen}\index{read=\texttt{read}}} \\
\multicolumn{2}{|X|}{\texttt{~case \dq\$line\dq~in}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~~.) echo \dq Ausgefuehrt\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~break;;}} \\
\multicolumn{2}{|X|}{\texttt{~~*) echo \dq\$line\dq ;;}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~esac}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -0,0 +1,15 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ cat }\textsl{Datei1}\texttt{ > }\textsl{Neu} & Schreibt den Inhalt der \textsl{Datei1} in die Datei \textsl{Neu}\index{cat=\texttt{cat}} \tabularnewline\STRUT
\texttt{\$ cat }\textsl{Datei2 Datei3}\texttt{ >{}> }\textsl{Neu} & Hängt den Inhalt der \textsl{Datei2} und der \textsl{Datei3} an die Datei \textsl{Neu} an\index{cat=\texttt{cat}} \tabularnewline\STRUT
\texttt{\$ mail }\textsl{name}\texttt{ < }\textsl{Neu} & Das Programm \texttt{mail} liest den Inhalt der Datei \textsl{Neu} \tabularnewline\STRUT
\texttt{\$ ls -l | grep }\textsl{\dq txt\dq}\texttt{ | sort } & Die Ausgabe des Befehls \texttt{ls -l} (Verzeichnisinhalt) wird an das Kommando \texttt{grep} weitergegeben, das darin nach \textsl{\dq txt\dq} sucht. Alle Zeilen die das Muster\index{Mustererkennung} enthalten werden anschließend an \texttt{sort} übergeben und landen dann sortiert auf der Standard-Ausgabe.\index{grep=\texttt{grep}}\index{sort=\texttt{sort}} \tabularnewline\STRUT
\texttt{\$ grep }\textsl{\dq txt\dq}\texttt{ * 2>\&1 | less } & In allen Dateien wird nach \textsl{\dq txt\dq} gesucht. Wenn dabei Fehler auftreten (weil z. B. auch Verzeichnisse im aktuellen Verzeichnis sind), werden die Fehlermeldungen an \texttt{less} weitergegeben. Dort werden sie dann seitenweise ausgegeben.\index{grep=\texttt{grep}}\index{less=\texttt{less}}
\end{longtable}

View File

@ -0,0 +1,12 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{cdrdao read-toc -{}-datafile - cd.toc}} \\
\multicolumn{2}{|X|}{\texttt{cdparanoia -q -R 1- - | cdrdao write -{}-buffers 64 cd.toc}} \\
\end{longtable}

View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{cat << }\textsl{EOF}} \\
\multicolumn{2}{|X|}{~~~Dieser Text wird zeilenweise ausgegeben,} \\
\multicolumn{2}{|X|}{~~~bis ein einzelnes EOF kommt.} \\
\multicolumn{2}{|X|}{\textsl{EOF}} \\
\hline
\multicolumn{2}{|X|}{Ein Here-Dokument: Nach dem \texttt{ << } wird ein sogenannter Delimiter angegeben. Alle folgenden Zeilen werden an die Standard-Eingabe von \texttt{cat} übergeben. Der Text wird durch ein erneutes Vorkommen des Delimiters (einzeln und am Zeilenanfang) beendet.\index{cat=\texttt{cat}}} \\
\end{longtable}

17
tab_beisp_exitcode.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ cp datei /tmp}} \\
\multicolumn{2}{|X|}{\texttt{\$ echo \$?}} \\
\multicolumn{2}{|X|}{\texttt{0}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ cp datie /tmp}} \\
\multicolumn{2}{|X|}{\texttt{cp: datie: Datei oder Verzeichnis nicht gefunden}} \\
\multicolumn{2}{|X|}{\texttt{\$ echo \$?}} \\
\multicolumn{2}{|X|}{\texttt{1}} \\
\end{longtable}

View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ lpr datei \&\& rm datei}\index{\&\&=\texttt{\&\&}}} \\
\end{longtable}

29
tab_beisp_for.tex Normal file
View File

@ -0,0 +1,29 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Seitenweises Formatieren der Dateien, die auf der Befehlszeile angegeben wurden, und speichern des jeweiligen Ergebnisses:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~pr \$file > \$file.tmp~~\# pr: Formatiert Textdateien}\index{!>=\texttt{!>}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Durchsuche Kapitel zur Erstellung einer Wortliste (wie \texttt{fgrep -f}):}} \\
\multicolumn{2}{|X|}{\texttt{for item in `cat program\_list`~~\# cat: Datei ausgeben}\index{cat=\texttt{cat}}\index{Backticks}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Pruefung der Kapitel auf\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~grep -c \dq\$item.[co]\dq~chap*~~\# grep: nach Muster\index{Mustererkennung} suchen}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}}\index{Anführungszeichen}\index{grep=\texttt{grep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn als neuen Dateinamen:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~name=`sed -n 's/NAME: //p' \$file`}\index{!==\texttt{!=}}\index{Backticks}\index{Ticks}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# sed: Skriptsprache zur}\index{sed=\texttt{sed}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# Textformatierung}} \\
\multicolumn{2}{|X|}{\texttt{~mv \$file \$name~~\# mv: Datei verschieben}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~\# bzw. umbenennen}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

16
tab_beisp_funktionen.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{count () \{}} \\
\multicolumn{2}{|X|}{\texttt{~ls -1 | wc -l~~\# ls: Liste aller Dateien im Verzeichnis}\index{Pipe}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -1 einspaltig}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\# wc: Word-Count, zählt Wörter}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -l Zeilen}} \\
\multicolumn{2}{|X|}{\texttt{\}}} \\
\end{longtable}

16
tab_beisp_if.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Füge eine 0 vor Zahlen kleiner 10 ein:}} \\
\multicolumn{2}{|X|}{\texttt{if [ \$counter -lt 10 ]; then}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~number=0\$counter; else number=\$counter; fi}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Lösche ein Verzeichnis, wenn es existiert:}} \\
\multicolumn{2}{|X|}{\texttt{if [ -d \$dir ]; then}\index{!!=\texttt{!!}}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~rmdir \$dir; fi~~\# rmdir: Verzeichnis löschen}} \\
\end{longtable}

13
tab_beisp_metazeichen.tex Normal file
View File

@ -0,0 +1,13 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ ls neu*} & Listet alle Dateien, die mit `neu' anfangen \tabularnewline\STRUT
\texttt{\$ ls neu?} & Listet `neuX', `neu4', aber nicht `neu10' \tabularnewline\STRUT
\texttt{\$ ls [D-R]*} & Listet alle Dateien, die mit einem Großbuchstaben\index{Großbuchstaben}\footnote{Natürlich wird in Shell-Skripten --- wie überall in der Unix-Welt --- zwischen Groß- und Kleinschreibung unterschieden.} zwischen D und R anfangen
\end{longtable}

33
tab_beisp_muster.tex Normal file
View File

@ -0,0 +1,33 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{Haus} & Die Zeichenfolge \textsl{Haus}. \tabularnewline\STRUT
\texttt{\^{}Haus} & \textsl{Haus} am Zeilenanfang. \tabularnewline\STRUT
\texttt{Haus\$} & \textsl{Haus} am Zeilenende. \tabularnewline\STRUT
\texttt{\^{}Haus\$} & \textsl{Haus} als einziges Wort in einer Zeile. \tabularnewline\STRUT
\texttt{[Hh]aus} & \textsl{Haus} oder \textsl{haus}. \tabularnewline\STRUT
\texttt{Ha[unl]s} & \textsl{Haus}, \textsl{Hals} oder \textsl{Hans}. \tabularnewline\STRUT
\texttt{[\^{}HML]aus} & Weder \textsl{Haus}, noch \textsl{Maus}, noch \textsl{Laus}. Jedoch muß die Zeichenfolge \textsl{aus} enthalten sein. \tabularnewline\STRUT
\texttt{Ha.s} & Der dritte Buchstabe ist ein beliebiges Zeichen. \tabularnewline\STRUT
\texttt{\^{}...\$} & Jede Zeile mit genau drei Zeichen. \tabularnewline\STRUT
\texttt{\^{}\textbackslash.} & Jede Zeile, die mit einem Punkt beginnt. \tabularnewline\STRUT
\texttt{\^{}\textbackslash.[a-z][a-z]} & Jede Zeile, die mit einem Punkt und zwei Kleinbuchstaben\index{Kleinbuchstaben} beginnt. \tabularnewline\STRUT
\texttt{\^{}\textbackslash.[a-z]\textbackslash\{2\textbackslash\}} & Wie oben, jedoch nur in grep und sed zulässig. \tabularnewline\STRUT
\texttt{\^{}[\^{}.]} & Jede Zeile, die nicht mit einem Punkt beginnt. \tabularnewline\STRUT
\texttt{Fehler*} & \textsl{Fehle} (!), \textsl{Fehler}, \textsl{Fehlers}, etc. \tabularnewline\STRUT
\texttt{\dq Wort\dq} & Ein Wort in Anführungszeichen. \tabularnewline\STRUT
\texttt{\dq *Wort\dq *} & Ein Wort mit beliebig vielen (auch keinen) Anführungszeichen. \tabularnewline\STRUT
\texttt{[A-Z][A-Z]*} & Ein oder mehrere Großbuchstaben\index{Großbuchstaben}. \tabularnewline\STRUT
\texttt{[A-Z]+} & Wie oben, jedoch nur in egrep und awk zulässig. \tabularnewline\STRUT
\texttt{[A-Z].*} & Ein Großbuchstabe\index{Großbuchstaben}, gefolgt von keinem oder beliebig vielen Zeichen. \tabularnewline\STRUT
\texttt{[A-Z]*} & Kein, ein oder mehrere Großbuchstaben\index{Großbuchstaben}. \tabularnewline\STRUT
\texttt{[a-zA-Z]} & Ein Buchstabe. \tabularnewline\STRUT
\texttt{[\^{}0-9a-zA-Z]} & Symbole (weder Buchstaben noch Zahlen). \tabularnewline\STRUT
\texttt{[0-9a-zA-Z]} & Jedes Alphanumerische Zeichen.
\end{longtable}

View File

@ -0,0 +1,14 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{[567]} & Eine der Zahlen \textsl{5}, \textsl{6} oder \textsl{7}. \tabularnewline\STRUT
\texttt{fuenf|sechs|sieben} & Eines der Worte \textsl{fuenf}, \textsl{sechs} oder \textsl{sieben}. \tabularnewline\STRUT
\texttt{80[234]?86} & \textsl{8086}, \textsl{80286}, \textsl{80386} oder \textsl{80486}. \tabularnewline\STRUT
\texttt{F(ahr|lug)zeug} & \textsl{Fahrzeug} oder \textsl{Flugzeug}.
\end{longtable}

13
tab_beisp_muster_ex.tex Normal file
View File

@ -0,0 +1,13 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\textbackslash<The} & Wörter wie \textsl{Theater} oder \textsl{Thema}. \tabularnewline\STRUT
\texttt{ung\textbackslash>} & Wörter wie \textsl{Teilung} oder \textsl{Endung}. \tabularnewline\STRUT
\texttt{\textbackslash<Wort\textbackslash>} & Das Wort \textsl{Wort}.
\end{longtable}

12
tab_beisp_muster_sed.tex Normal file
View File

@ -0,0 +1,12 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{0\textbackslash\{5,\textbackslash\}} & Fünf oder mehr Nullen in Folge. \tabularnewline\STRUT
\texttt{[0-9]-[0-9]\textbackslash\{3\textbackslash\}-[0-9]\textbackslash\{5\textbackslash\}-[0-9X]} & ISBN-Nummern in der Form \textsl{n-nnn-nnnnn-n}, das letzte Zeichen kann auch ein X sein.
\end{longtable}

15
tab_beisp_nullbefehl.tex Normal file
View File

@ -0,0 +1,15 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{if who | grep \$1 > /dev/null~~\# who: Liste der Benutzer}\index{Pipe}\index{\$n=\texttt{\$}$n$}\index{!>=\texttt{!>}}\index{who=\texttt{who}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\# grep: Suche nach Muster}} \\
\multicolumn{2}{|X|}{\texttt{then :~~~~~~~~~~~~~~~~~~~~~~~~\# tut nichts}} \\
\multicolumn{2}{|X|}{\texttt{~else echo \dq Benutzer \$1 ist nicht angemeldet\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{fi}} \\
\end{longtable}

18
tab_beisp_quoting.tex Normal file
View File

@ -0,0 +1,18 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ echo 'Ticks \dq schützen\dq~Anführungszeichen'}} \\
\multicolumn{2}{|X|}{\texttt{Ticks \dq schützen\dq~Anführungszeichen}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Ist dies ein \textbackslash\dq Sonderfall\textbackslash\dq ?\dq}} \\
\multicolumn{2}{|X|}{\texttt{Ist dies ein \dq Sonderfall\dq ?}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Sie haben `ls | wc -l` Dateien in `pwd`\dq}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{Sie haben 43 Dateien in /home/rschaten}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Der Wert von \textbackslash\$x ist \$x\dq}} \\
\multicolumn{2}{|X|}{\texttt{Der Wert von \$x ist 100}} \\
\end{longtable}

30
tab_beisp_sed-ex.tex Normal file
View File

@ -0,0 +1,30 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{s/.*/( \& )/} & Wiederholt die ganze Zeile, fügt aber Klammern hinzu. \tabularnewline\STRUT
\texttt{s/.*/mv \& \&.old/} & Formt eine Wortliste (ein Wort pro Zeile) zu \texttt{mv}-Befehlen um. \tabularnewline\STRUT
\texttt{/\^{}\$/d} & Löscht Leerzeilen. \tabularnewline\STRUT
\texttt{:g/\^{}\$/d} & Wie oben, im ex-Editor. \tabularnewline\STRUT
\texttt{/\^{}[\Ovalbox{SPACE}\Ovalbox{TAB}]*\$/d} & Löscht Leerzeilen und Zeilen, die nur aus Leerzeichen oder Tabulatoren bestehen. \tabularnewline\STRUT
\texttt{/\^{}[\Ovalbox{SPACE}\Ovalbox{TAB}]*\$/d} & Löscht Leerzeilen und Zeilen, die nur aus Leerzeichen oder Tabulatoren bestehen. \tabularnewline\STRUT
\texttt{:g/\^{}[\Ovalbox{SPACE}\Ovalbox{TAB}]*\$/d} & Wie oben, im ex-Editor. \tabularnewline\STRUT
\texttt{/\Ovalbox{SPACE}\Ovalbox{SPACE}*/\Ovalbox{SPACE}/g} & Wandelt ein oder mehrere Leerzeichen in ein Leerzeichen um. \tabularnewline\STRUT
\texttt{:\%s/\Ovalbox{SPACE}\Ovalbox{SPACE}*/\Ovalbox{SPACE}/g} & Wie oben, im ex-Editor. \tabularnewline\STRUT
\texttt{:s/[0-9]/Element \&:/} & Wandelt (in der aktuellen Zeile) eine Zahl in ein Label für ein Element um. \tabularnewline\STRUT
\texttt{:s} & Wiederholt die Substitution beim ersten Vorkommen. \tabularnewline\STRUT
\texttt{:\&} & Wie oben. \tabularnewline\STRUT
\texttt{:sg} & Wie oben, aber für alle Vorkommen in einer Zeile. \tabularnewline\STRUT
\texttt{:\&g} & Wie oben. \tabularnewline\STRUT
\texttt{:\%\&g} & Wiederholt die Substitution im ganzen Puffer. \tabularnewline\STRUT
\texttt{:.,\$s/Wort/\textbackslash U\&/g} & Wandelt von der aktuellen bis zur letzten Zeile das Wort \textsl{Wort} in Großschreibung\index{Großschreibung} um. \tabularnewline\STRUT
\texttt{:\%s/.*/\textbackslash L\&/} & Wandelt die gesamte Datei in Kleinschreibung um. \tabularnewline\STRUT
\texttt{:s/\textbackslash<./\textbackslash u\&/g} & Wandelt den ersten Buchstaben jedes Wortes in der aktuellen Zeile in Großschreibung\index{Großschreibung} um. \tabularnewline\STRUT
\texttt{:\%s/ja/nein/g} & Ersetzt das Wort \textsl{ja} durch \textsl{nein}. \tabularnewline\STRUT
\texttt{:\%s/Ja/\~{}/g} & Ersetzt global ein anderes Wort (\textsl{Ja}) durch \textsl{nein} (Wiederverwendung des vorherigen Ersatzmusters).
\end{longtable}

17
tab_beisp_until.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Warten, bis sich der Administrator einloggt:}} \\
\multicolumn{2}{|X|}{\texttt{until who | grep \dq root\dq; do}\index{;=\texttt{;}}\index{Anführungszeichen}\index{who=\texttt{who}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# who: Liste der Benutzer}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# grep: Suchen nach Muster}\index{Mustererkennung}} \\
\multicolumn{2}{|X|}{\texttt{~sleep 2~~\# sleep: warten}\index{sleep=\texttt{sleep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\texttt{echo \dq Der Meister ist anwesend\dq}\index{Anführungszeichen}} \\
\end{longtable}

View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erhält. \tabularnewline\STRUT
\texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern müssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT
\texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten würde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT
\texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist.\footnote{Der Befehl \texttt{date} gibt das Datum zurück.} \tabularnewline\STRUT
\texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enthält. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT
\texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}.
\end{longtable}

16
tab_beisp_while.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Zeilenweise Ausgabe aller Aufrufparameter:}\index{Parameter}} \\
\multicolumn{2}{|X|}{\texttt{while [ -n \dq\$1\dq ]; do}\index{\$n=\texttt{\$}$n$}\index{;=\texttt{;}}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~echo \$1}} \\
\multicolumn{2}{|X|}{\texttt{~shift~~\# mit shift werden die Parameter nach}\index{shift=\texttt{shift}}\index{Parameter}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~\# Links geshiftet (aus \$2 wird \$1)}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

17
tab_beisp_while_for.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Ausgabe der Zahlen von 1 bis 100:}} \\
\multicolumn{2}{|X|}{\texttt{i=1}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\texttt{while [ \$i -le 100 ]}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~echo \$i}} \\
\multicolumn{2}{|X|}{\texttt{~i=`expr \$i + 1`}\index{expr=\texttt{expr}}\index{+=\texttt{+}}\index{!==\texttt{!=}}\index{Backticks}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

11
tab_break.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{break }\textsl{[ n ]}} \\
\end{longtable}

15
tab_case.tex Normal file
View File

@ -0,0 +1,15 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{case }\textsl{Wert}\texttt{ in}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~\vdots}} \\
\multicolumn{2}{|X|}{\texttt{esac}} \\
\end{longtable}

11
tab_continue.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{continue }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{Befehl}\texttt{ >\&}\textsl{n} & Standard-Ausgabe von \textsl{Befehl} an den Dateideskriptor \textsl{n} übergeben. \tabularnewline\STRUT
\textsl{Befehl m}\texttt{>\&}\textsl{n} & Der gleiche Vorgang, nur wird die Ausgabe, die normalerweise an den Dateideskriptor \textsl{m} geht, an den Dateideskriptor \textsl{n} übergeben. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ >\&-} & Schließt die Standard-Ausgabe. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ <\&}\textsl{n} & Standard-Eingabe für \textsl{Befehl} wird vom Dateideskriptor \textsl{n} übernommen. \tabularnewline\STRUT
\textsl{Befehl m}\texttt{<\&}\textsl{n} & Der gleiche Vorgang, nur wird die Eingabe, die normalerweise vom Dateideskriptor \textsl{m} stammt, aus dem Dateideskriptor \textsl{n} übernommen. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ <\&-} & Schließt die Standard-Eingabe.
\end{longtable}

View File

@ -0,0 +1,15 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{Befehl}\texttt{ > }\textsl{Datei} & Standard-Ausgabe von \textsl{Befehl} in \textsl{Datei} schreiben. Die \textsl{Datei} wird überschrieben, wenn sie schon bestand. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ >{}> }\textsl{Datei} & Standard-Ausgabe von \textsl{Befehl} an \textsl{Datei} anhängen. Die \textsl{Datei} wird erstellt, wenn sie noch nicht bestand\footnote{In einigen sehr alten Versionen der \texttt{sh}\index{Bourne-Shell} und in der \texttt{csh}\index{C-Shell} wird die Datei nicht erstellt. Um hier sicherzugehen, sollte die Datei vorher mittels \texttt{touch}\index{touch=\texttt{touch}} erstellt werden.}. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ < }\textsl{Datei} & Standard-Eingabe für \textsl{Befehl} aus \textsl{Datei} lesen. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ << }\textsl{Delimiter} & Ein Here-Dokument: Der \textsl{Befehl} erhält den folgenden Abschnitt als Standard-Eingabe. Der Abschnitt endet, sobald der Delimiter am Zeilenanfang gefunden wird. Der Delimiter kann beliebig gewählt werden (siehe Beispiel). \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ | }\textsl{Befehl2} & Die Standard-Ausgabe von \textsl{Befehl1} wird an die Standard-Eingabe von \textsl{Befehl2} übergeben. Mit diesem Mechanismus können Programme als `Filter' für den Datenstrom eingesetzt werden. Das verwendete Zeichen heißt Pipe.
\end{longtable}

View File

@ -0,0 +1,15 @@
\begin{longtable}{|X|X|X|X|}
% KILLED & LINE!!!! \kill
\hline
Dateideskriptor & Name & Gebräuchliche Abkürzung & Typischer Standard \\
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
0 & Standard-Eingabe & stdin & Tastatur \tabularnewline\STRUT
1 & Standard-Ausgabe & stdout & Terminal\index{Terminal} \tabularnewline\STRUT
2 & Fehlerausgabe & stderr & Terminal
\end{longtable}

View File

@ -0,0 +1,14 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{Befehl}\texttt{ 2> }\textsl{Datei} & Fehlerausgabe von \textsl{Befehl} in \textsl{Datei} schreiben. Die Standard-Ausgabe bleibt unverändert (z. B. auf dem Terminal). \tabularnewline\STRUT
\textsl{Befehl}\texttt{ > }\textsl{Datei}\texttt{ 2>\&1} & Fehlerausgabe und Standard-Ausgabe von \textsl{Befehl} werden in die \textsl{Datei} geschrieben. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ > }\textsl{D1}\texttt{ 2> }\textsl{D2} & Standard-Ausgabe erfolgt in die Datei \textsl{D1}; Fehlerausgabe in die Datei \textsl{D2}. \tabularnewline\STRUT
\textsl{Befehl}\texttt{ | tee }\textsl{Dateien} & Die Ausgaben von \textsl{Befehl} erfolgen an der Standard-Ausgabe (in der Regel: Terminal), zusätzlich wird sie vom Kommando \texttt{tee} in die \textsl{Dateien} geschrieben.\index{tee=\texttt{tee}}
\end{longtable}

11
tab_exit.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{exit }\textsl{[ n ]}} \\
\end{longtable}

14
tab_for.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

17
tab_if.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{if }\textsl{Bedingung1}} \\
\multicolumn{2}{|X|}{\texttt{then }\textsl{Befehle1}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ elif }\textsl{Bedingung2}} \\
\multicolumn{2}{|X|}{\texttt{ then }\textsl{Befehle2 ]}} \\
\multicolumn{2}{|X|}{\texttt{ \vdots}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ else }\textsl{Befehle3 ]}} \\
\multicolumn{2}{|X|}{\texttt{fi}} \\
\end{longtable}

19
tab_metazeichen.tex Normal file
View File

@ -0,0 +1,19 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{*} & Eine Folge von keinem, einem oder mehreren Zeichen \tabularnewline\STRUT
\texttt{?} & Ein einzelnes Zeichen \tabularnewline\STRUT
\texttt{[}\textsl{abc}\texttt{]} & Übereinstimmung mit einem beliebigen Zeichen in der Klammer \tabularnewline\STRUT
\texttt{[}\textsl{a}\texttt{-}\textsl{q}\texttt{]} & Übereinstimmung mit einem beliebigen Zeichen aus dem angegebenen Bereich \tabularnewline\STRUT
\texttt{[!}\textsl{abc}\texttt{]} & Übereinstimmung mit einem beliebigen Zeichen, das nicht in der Klammer ist\footnote{Bei einigen älteren Versionen der Bash muß an Stelle des Rufzeichens ein \texttt{\^} geschrieben werden.} \tabularnewline\STRUT
\texttt{\~} & Home-Verzeichnis des aktuellen Benutzers\index{Home-Verzeichnis} \tabularnewline\STRUT
\texttt{\~{}}\textsl{name} & Home-Verzeichnis des Benutzers \textsl{name} \tabularnewline\STRUT
\texttt{\~{}+} & Aktuelles Verzeichnis \tabularnewline\STRUT
\texttt{\~{}-} & Vorheriges Verzeichnis
\end{longtable}

View File

@ -0,0 +1,20 @@
\begin{longtable}{|l|c|c|c|X|}
% KILLED & LINE!!!! \kill
\hline
~ & ex & sed & ed & ~ \\
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\textbackslash} & $\bullet$ & $\bullet$ & $\bullet$ & Sonderbedeutung des nächsten Zeichens aufheben. \tabularnewline\STRUT
\texttt{\textbackslash\textsl{n}} & $\bullet$ & $\bullet$ & $\bullet$ & Verwendet das in \texttt{\textbackslash( \textbackslash)} gespeicherte Muster erneut. \tabularnewline\STRUT
\texttt{\&} & $\bullet$ & $\bullet$ & ~ & Verwendet das vorherige Suchmuster erneut. \tabularnewline\STRUT
\texttt{\~} & $\bullet$ & ~ & ~ & Verwendet das vorherige Ersatzmuster erneut. \tabularnewline\STRUT
\texttt{\textbackslash u \textbackslash U} & $\bullet$ & ~ & ~ & Ändert das (die) Zeichen auf Großschreibung\index{Großschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash l \textbackslash L} & $\bullet$ & ~ & ~ & Ändert das (die) Zeichen auf Kleinschreibung\index{Kleinschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash E} & $\bullet$ & ~ & ~ & Hebt das vorangegangene \texttt{\textbackslash U} oder \texttt{\textbackslash L} auf. \tabularnewline\STRUT
\texttt{\textbackslash e} & $\bullet$ & ~ & ~ & Hebt das vorangegangene \texttt{\textbackslash u} oder \texttt{\textbackslash l} auf.
\end{longtable}

View File

@ -0,0 +1,20 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\textbackslash} & Hebt die spezielle Bedeutung des nächsten Zeichens auf. \tabularnewline\STRUT
\texttt{\textbackslash\textsl{n}} & Ruft das \textsl{n}te Muster aus dem Puffer ab (siehe oben, unter \texttt{\textbackslash( \textbackslash)}. Dabei ist \textsl{n} eine Zahl zwischen 1 und 9. \tabularnewline\STRUT
\texttt{\&} & Verwendet das vorherige Suchmuster erneut als Teil eines Ersatzmusters. \tabularnewline\STRUT
\texttt{\~} & Verwendet das vorherige Ersatzmuster erneut im momentanen Ersatzmuster. \tabularnewline\STRUT
\texttt{\textbackslash u} & Ändert das erste Zeichen des Ersatzmusters auf Großschreibung\index{Großschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash U} & Ändert alle Zeichen des Ersatzmusters auf Großschreibung\index{Großschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash l} & Ändert das erste Zeichen des Ersatzmusters auf Kleinschreibung\index{Kleinschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash L} & Ändert alle Zeichen des Ersatzmusters auf Kleinschreibung\index{Kleinschreibung}. \tabularnewline\STRUT
\texttt{\textbackslash e} & Hebt das vorangegangene \texttt{\textbackslash u} oder \texttt{\textbackslash l} auf. \tabularnewline\STRUT
\texttt{\textbackslash E} & Hebt das vorangegangene \texttt{\textbackslash U} oder \texttt{\textbackslash L} auf.
\end{longtable}

View File

@ -0,0 +1,25 @@
\begin{longtable}{|l|c|c|c|c|c|c|c|X|}
% KILLED & LINE!!!! \kill
\hline
~ & ed & ex & vi & sed & awk & grep & egrep & ~ \tabularnewline
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{.} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Ein beliebiges Zeichen. \tabularnewline\STRUT
\texttt{*} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Kein, ein oder mehrere Vorkommen des vorhergehenden Ausdrucks. \tabularnewline\STRUT
\texttt{\^} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Zeilenanfang. \tabularnewline\STRUT
\texttt{\$} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Zeilenende. \tabularnewline\STRUT
\texttt{\textbackslash} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Hebt die Sonderbedeutung des folgenden Zeichens auf. \tabularnewline\STRUT
\texttt{[ ]} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & Ein Zeichen aus einer Gruppe. \tabularnewline\STRUT
\texttt{\textbackslash( \textbackslash)} & $\bullet$ & $\bullet$ & ~ & $\bullet$ & ~ & ~ & ~ & Speichert das Muster zur späteren Wiederholung. \tabularnewline\STRUT
\texttt{\textbackslash\{ \textbackslash\}} & $\bullet$ & ~ & ~ & $\bullet$ & ~ & $\bullet$ & ~ & Vorkommensbereich. \tabularnewline\STRUT
\texttt{\textbackslash< \textbackslash>} & $\bullet$ & $\bullet$ & $\bullet$ & ~ & ~ & ~ & ~ & Wortanfang oder -ende. \tabularnewline\STRUT
\texttt{+} & ~ & ~ & ~ & ~ & $\bullet$ & ~ & $\bullet$ & Ein oder mehrere Vorkommen des vorhergehenden Ausdrucks. \tabularnewline\STRUT
\texttt{?} & ~ & ~ & ~ & ~ & $\bullet$ & ~ & $\bullet$ & Kein oder ein Vorkommen des vorhergehenden Ausdrucks. \tabularnewline\STRUT
\texttt{|} & ~ & ~ & ~ & ~ & $\bullet$ & ~ & $\bullet$ & Trennt die für die Übereinstimmung verfügbaren Alternativen. \tabularnewline\STRUT
\texttt{( )} & ~ & ~ & ~ & ~ & $\bullet$ & ~ & $\bullet$ & Gruppiert Ausdrücke für den Test.
\end{longtable}

View File

@ -0,0 +1,23 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{.} & Steht für ein beliebiges \emph{einzelnes} Zeichen, mit Ausnahme des Zeilenendezeichens. \tabularnewline\STRUT
\texttt{*} & 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 \texttt{.*} für eine beliebige Anzahl eines beliebigen Zeichens. \tabularnewline\STRUT
\texttt{\^} & Übereinstimmung, wenn der folgende Ausdruck am Zeilenanfang\index{Zeilenanfang} steht. \tabularnewline\STRUT
\texttt{\$} & Übereinstimmung, wenn der vorhergehende Ausdruck am Zeilenende\index{Zeilenende} steht. \tabularnewline\STRUT
\texttt{\textbackslash} & Schaltet die Sonderbedeutung des nachfolgenden Zeichens ab. \tabularnewline\STRUT
\texttt{[ ]} & Steht für \emph{ein} beliebiges Zeichen aus der eingeklammerten Gruppe. Mit einem Bindestrich kann man einen Bereich aufeinanderfolgender Zeichen auswählen (\texttt{[a-e]}). Ein Zirkumflex (\texttt{\^}) wirkt als Umkehrung: \texttt{[\^{}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. \tabularnewline\STRUT
\texttt{\textbackslash( \textbackslash)} & Speichert das Muster zwischen \texttt{\textbackslash(} und \texttt{\textbackslash)} in einem speziellen Puffer. In einer Zeile können bis zu neun solcher Puffer belegt werden. In Substitutionen können sie über die Zeichenfolgen \texttt{\textbackslash 1} bis \texttt{\textbackslash 9} wieder benutzt werden. \tabularnewline\STRUT
\texttt{\textbackslash\{ \textbackslash\}} & Steht für den Vorkommensbereich des unmittelbar vorhergehenden Zeichens. \texttt{\textbackslash\{}\textsl{n}\texttt{\textbackslash\}} bezieht sich auf genau \textsl{n} Vorkommen, \texttt{\textbackslash\{}\textsl{n}\texttt{,\textbackslash\}} auf mindestens \textsl{n} Vorkommen und \texttt{\textbackslash\{}\textsl{n}\texttt{,}\textsl{m}\texttt{\textbackslash\}} auf eine beliebige Anzahl von Vorkommen zwischen \textsl{n} und \textsl{m}. Dabei müssen \textsl{n} und \textsl{m} im Bereich zwischen 0 und 256 liegen. \tabularnewline\STRUT
\texttt{\textbackslash< \textbackslash>} & Steht für ein Zeichen am Anfang (\texttt{\textbackslash<}) oder am Ende (\texttt{\textbackslash>}) eines Wortes. \tabularnewline\STRUT
\texttt{+} & Steht für ein oder mehrere Vorkommen des vorhergehenden regulären Ausdrucks (äquivalent zu \texttt{\{1,\}}). \tabularnewline\STRUT
\texttt{?} & Steht für kein oder ein Vorkommen des vorhergehenden Ausdrucks (äquivalent zu \texttt{\{0,1\}}). \tabularnewline\STRUT
\texttt{|} & Übereinstimmung, wenn entweder der vorhergehende oder der nachfolgende reguläre Ausdruck übereinstimmen. \tabularnewline\STRUT
\texttt{( )} & Steht für die eingeschlossene Gruppe von regulären Ausdrücken.
\end{longtable}

View File

@ -0,0 +1,19 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{;} & Befehls-Trennzeichen\index{Befehls>-Trennzeichen} \tabularnewline\STRUT
\texttt{\&} & Hintergrund-Verarbeitung \tabularnewline\STRUT
\texttt{( )} & Befehlsfolge\index{Befehls>-folge} \tabularnewline\STRUT
\texttt{|} & Pipe \tabularnewline\STRUT
\texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT
\texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} für Dateinamen \tabularnewline\STRUT
\texttt{` ` }(Backticks\footnote{Man erhält sie durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
\texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT
\texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} & Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der Variable \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} abgelegt. Man kann diese Variable auch überschreiben, um elegant Strings zu zerlegen.}
\end{longtable}

25
tab_quoting_zeichen.tex Normal file
View File

@ -0,0 +1,25 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\dq~\dq} & (Anführungszeichen) Alles zwischen diesen Zeichen ist
buchstabengetreu zu interpretieren. Ausnahmen sind folgende Zeichen, die ihre
spezielle Bedeutung beibehalten: \texttt{\$ ` \dq} \tabularnewline\STRUT
\texttt{' '} & (Ticks\footnote{Sie liegen auf der Tastatur über der Raute.})
Alls zwischen diesen Zeichen wird wörtlich genommen, mit Ausnahme eines
weiteren \texttt{'} oder eines Backslashes (\texttt{\textbackslash})
\tabularnewline\STRUT
\texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem
\textbackslash wird wörtlich genommen. Anwendung z. B. innerhalb von
\texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten.
Häufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder
um ein \textbackslash -Zeichen selbst anzugeben.
\end{longtable}

16
tab_signale.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|l|X|}
% KILLED & LINE!!!! \kill
\hline
Nummer & Name & Bedeutung \\
\hline
% \endfirsthead
\endhead
\hline
\endfoot
% \endlastfoot
0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgelöst. \tabularnewline\STRUT
1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT
2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}-\Ovalbox{C}). \tabularnewline\STRUT
15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet.
\end{longtable}

14
tab_until.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{until }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -0,0 +1,16 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{Variable}\texttt{=}\textsl{Wert} & Setzt die \textsl{Variable} auf den \textsl{Wert}. Dabei ist unbedingt darauf zu achten, daß zwischen dem Variablennamen und dem Gleichheitszeichen keine Leerzeichen stehen. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Die Klammern müssen nicht mit angegeben werden, wenn die \textsl{Variable} von Trennzeichen umgeben ist. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt, und \textsl{Variable} erhält den \textsl{Wert}. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} ausgegeben und die Shell beendet. Wenn kein \textsl{Wert} angegeben wurde, wird der Text \texttt{parameter null or not set} ausgegeben. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}} & Nutzt den \textsl{Wert}, falls die \textsl{Variable} gesetzt ist, andernfalls nichts.
\end{longtable}

View File

@ -0,0 +1,20 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$}$n$ & Aufrufparameter\index{Parameter} mit der Nummer $n$, $0<=n<=9$. \texttt{\$0} enthält den Namen des gerade laufenden Skripts. \tabularnewline\STRUT
\texttt{\$*} & Alle Aufrufparameter\index{Aufrufparameter|see{Parameter}}\index{Parameter}. \texttt{\dq\$*\dq} enthält alle Aufrufparameter in einem String. \tabularnewline\STRUT
\texttt{\$@} & Alle Aufrufparameter\index{Parameter}. \texttt{\dq\$@\dq} enthält alle Aufrufparameter\index{Parameter}, wobei jeder für sich ein separater String bleibt. \tabularnewline\STRUT
\texttt{\$\#} & Anzahl der Aufrufparameter\index{Parameter} \tabularnewline\STRUT
\texttt{\$?} & Rückgabewert des letzten Kommandos \tabularnewline\STRUT
\texttt{\$\$} & Prozeßnummer der aktiven Shell \tabularnewline\STRUT
\texttt{\$!} & Prozeßnummer des letzten Hintergrundprozesses \tabularnewline\STRUT
\texttt{\$ERRNO} & Fehlernummer des letzten fehlgeschlagenen Systemaufrufs \tabularnewline\STRUT
\texttt{\$PWD} & Aktuelles Verzeichnis (wird durch \texttt{cd} gesetzt\footnote{Durch das Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt.}) \tabularnewline\STRUT
\texttt{\$OLDPWD} & Vorheriges Verzeichnis (wird durch \texttt{cd} gesetzt)
\end{longtable}

14
tab_while.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{while }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

45
was_ist_die_shell.tex Normal file
View File

@ -0,0 +1,45 @@
\chapter{Was ist die Shell?}\index{Shell}
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.
\section{Sinn und Zweck}
In einem klassischen Unix-System (ohne die grafische Oberfläche X) greifen die Benutzer über Terminals\index{Terminal} 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{itemize}
\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{itemize}
Ursprünglich handelte es sich dabei um ein relativ einfaches Programm, der Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist praktisch die "`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.
\section{Die Qual der Wahl}
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.
\medskip\emph{Einfach-Shells:}\nopagebreak
\begin{itemize}
\item Die Bourne-\index{Bourne-Shell|textbf}\index{Shell>Bourne-|see{Bourne-Shell}} oder Standard-Shell\index{Shell>Standard-|see{Bourne-Shell}}\index{Standard-Shell|see{Bourne-Shell}} (\texttt{sh}\index{sh=\texttt{sh}|see{Bourne-Shell}}) 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\index{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 Korn-Shell\index{Korn-Shell|textbf}\index{Shell>Korn-|see{Korn-Shell}} (\texttt{ksh}\index{ksh=\texttt{ksh}|see{Korn-Shell}}), eine Weiterentwicklung der Bourne-Shell, erlaubt das editieren in der Befehlszeile. Außerdem gibt es hier History\index{History}-Funktionen\footnote{History-Funktionen ermöglichen es dem Benutzer, einfach auf zurückliegende Befehle zurückgreifen zu können.}, eine Ganzzahl-Arithmetik, verbesserte Möglichkeiten zur Mustererkennung, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abkürzung für einen Befehl. Beispielsweise kann man das Häufig benutzte \texttt{ls -la} einfach durch \texttt{la} ersetzen.} und das Job-Controlling\footnote{Unter Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe der Benutzer die Ausführung von Prozessen selektiv stoppen oder fortsetzen kann}\index{Job-Controlling}. Außerdem bietet die Korn-Shell im Gegensatz zu fast allen anderen Shells die Möglichkeit, Aliase und Shell-Funktionen an Subshells zu vererben.
\item Die C-Shell \index{C-Shell|textbf}\index{Shell>C-|see{C-Shell}} (\texttt{csh}\index{csh=\texttt{csh}|see{C-Shell}}) bietet ähnliche Annehmlichkeiten wie die 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{itemize}
\medskip\emph{Komfort-Shells:}\nopagebreak
\begin{itemize}
\item Die Bourne-Again-Shell\index{Bourne-Again-Shell|textbf}\index{Shell>Bourne-Again-|see{Bourne-Again-Shell}}\index{Shell>Bash|see{Bourne-Again-Shell}} (\texttt{bash}\index{bash=\texttt{bash}|see{Bourne-Again-Shell}}) ist voll abwärtskompatibel zur 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.
Die Bash unterstützt Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist das automatische Vervollständigen von Dateinamen\index{Dateinamen} gemeint.}, History-Funktionen, Aliase\index{Aliase}, eine Ganzzahl-Arithmetik und indizierte Arrays\index{Array}.
\item Die TENEX-C-Shell\index{TENEX-C-Shell|textbf}\index{Shell>TENEX-C-|see{TENEX-C-Shell}} (\texttt{tcsh}\index{tcsh=\texttt{tcsh}|see{TENEX-C-Shell}}) verhält sich zur C-Shell wie die Bourne-Again-Shell zur Standard-Shell. Sie ist voll kompatibel, bietet aber Komfort-Funktionen wie Kommandozeilen-Editierung, programmierbare Auto-Completion\index{Auto-Completion}, Rechtschreibhilfen und eine History.
\item Die Z-Shell\index{Z-Shell|textbf}\index{Shell>Z-|see{Z-Shell}} (\texttt{zsh}\index{zsh=\texttt{zsh}|see{Z-Shell}}) ähnelt der Korn-Shell, enthält aber viele Erweiterungen. Die Z-Shell unterstützt Kommandozeilen-Editing, programmierbares Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History. Zudem ist eine Rechtschreibprüfung eingebaut.
\end{itemize}
\medskip\emph{Exoten:}\medskip\nopagebreak
Desweiteren gibt es noch eine Reihe weiterer Shells, die aber nur selten eingesetzt werden. Dazu gehören die \texttt{ash}\index{ash|textbf}\index{Shell>ash=\texttt{ash}|see{ash}} (Ein Bourne-Shell-Clone für Rechner mit wenig Speicher.), \texttt{rc}\index{rc|textbf}\index{Shell>rc=\texttt{rc}|see{rc}} (Noch ein Bourne-Shell-Clone, ursprünglich aus AT\&T Plan 9. Klein, schnell und mit eine C-ähnlichen Syntax.), \texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein und schnell, bietet eine Lisp-ähnliche Sprache), \texttt{sash}\index{sash|textbf}\index{Shell>sash=\texttt{sash}|see{sash}} (System Administrator's Shell - eine statisch gelinkte Shell mit integrierten Standard-Kommandos.).
Diese Liste ist bei weitem nicht vollständig.

124
werkzeugkasten.tex Normal file
View File

@ -0,0 +1,124 @@
\chapter{Nützliche Shell-Kommandos}
Durch die gezeigten Steuerungsmöglichkeiten stehen dem Shell-Pro\-grammie\-rer
Möglichkeiten offen, fast alle gängigen Algorithmen zu implementieren. Es ist
tatsächlich in der Shell möglich, Sortier- oder Suchfunktionen zu schreiben.
Leider kommt aber an dieser Stelle einer der bedeutendsten Nachteile der Shell
zum tragen: Die Geschwindigkeit.
In einem Shell-Skript wird für jedes externe Kommando\footnote{Externe
Kommandos sind solche, die nicht direkt in der Shell enthalten sind, für die
also eine eigene Datei aufgerufen wird.} ein eigener Prozeß gestartet. Das
kostet natürlich Zeit und Speicher.
Zeitkritische Anwendungen sind also kein Einsatzgebiet für Shell-Skripte. Die
schreibt man besser in Perl, oder noch besser in einer `compilierten' Sprache
wie C oder C++.
Es stehen jedoch an der Shell viele sehr nützliche externe Kommandos zur
Verfügung, die einem die Entwicklung entsprechender eigener Routinen ersparen.
Diese externen Kommandos sind zudem in anderen Sprachen geschrieben worden, so
daß sie schneller ablaufen als jedes Shell-Skript. Man kommt als
Shell-Programmierer nicht sinnvoll um den Einsatz dieser Programme herum.
In diesem Abschnitt sollen einige dieser Programme mit typischen
Einsatzmöglichkeiten vorgestellt werden. Eine vollständige Beschreibung wäre
(wenn überhaupt möglich) viel zu lang, um an dieser Stelle untergebracht zu
werden. Für ausführlichere Beschreibungen empfiehlt sich das Studium der
Man-Pages oder der Kauf eines entsprechenden Buches. Am besten macht man
natürlich beides. ;-)
\section{Ein- und Ausgabe}
TODO!!!
\subsection{echo}
TODO!!!
\LTXtable{\textwidth}{tab_beisp_exitcode.tex}
\subsection{cat}
TODO!!!
\subsection{read}
TODO!!!
\section{Pfade und Dateien}
TODO!!!
\subsection{basename}
TODO!!!
\subsection{touch}
TODO!!!
\section{Pipes manipulieren}
TODO!!!
\subsection{grep}
TODO!!!
\subsection{sed}
TODO!!!
\subsection{awk}
TODO!!!
\subsection{sort}
TODO!!!
\subsection{tee}
TODO!!!
\subsection{wc}
TODO!!!
\section{Sonstige Befehle}
TODO!!!
\subsection{script}
TODO!!!
\subsection{seq}
TODO!!!
\subsection{expr}
TODO!!!
\subsection{bc}
TODO!!!
\subsection{kill}
TODO!!!
\subsection{sleep}
TODO!!!
\subsection{who}
TODO!!!

View File

@ -0,0 +1,438 @@
\chapter{Wie sieht ein Shell-Skript aus?}
Wie schon erwähnt, kann ein Shell-Skript beinahe alles, was eine `richtige' Programmiersprache auch kann. Bei der Entwicklung sollte man nur bedenken, daß gerade die Ausführung von externen Kommandos --- und das ist eine der Standard-Techniken bei der Shell-Programmierung --- nur sehr langsam vonstatten geht. Für Anwendungen bei denen z. B. viele Rechnungen oder Stringbearbeitungen gemacht werden müssen, sollte man also ggf. die Benutzung einer anderen Sprache, beispielsweise Perl\index{Perl}, in Erwägung ziehen.
In der Shell stehen viele Mechanismen zur Verfügung, die auch aus anderen Sprachen bekannt sind. Um den Umfang dieses Dokuments nicht zu sprengen, werden an dieser Stelle nur die wichtigsten vorgestellt.
\section{Grundsätzliches}
Zunächst soll die Frage geklärt werden, wie man überhaupt ein ausführbares Shell-Skript schreibt. Dabei wird vorausgesetzt, daß dem Benutzer der Umgang mit mindestens einem Texteditor\index{Texteditor} (\texttt{vi}\index{vi=\texttt{vi}}, \texttt{emacs}\index{emacs=\texttt{emacs}} etc.) bekannt ist.
\subsection{HowTo}
Zunächst muß mit Hilfe des Editors eine Textdatei angelegt werden, in die der `Quelltext' geschrieben wird. Wie der aussieht, sollte man anhand der folgenden Abschnitte und der Beispiele im Anhang erkennen können. Beim Schreiben sollte man nicht mit den Kommentaren\index{Kommentar} geizen, da ein Shell-Skript auch schon mal sehr unleserlich werden kann.
Nach dem Abspeichern der Datei unter einem geeigneten Namen\footnote{Bitte
\emph{nicht} den Namen \texttt{test}\index{test=\texttt{test}} verwenden. Es
existiert ein Unix-Systemkommando mit diesem Namen. Dieses steht fast immer
eher im Pfad, d. h. beim Kommando \texttt{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
\texttt{test}-Kommando unter \ref{bedingungen}.} muß die sie ausführbar gemacht
werden. Das geht mit dem Unix-Kommando
\texttt{chmod}\index{chmod=\texttt{chmod}}. Rechte können unter Unix getrennt
für den Benutzer (user, \texttt{u}), die Gruppe (group, \texttt{g}) oder andere
(others, \texttt{o}) vergeben werden. Außerdem kann man die Rechte für alle
Gruppen zusammen (all, a) setzen. Man kann getrennt die Rechte für das lesen
(read, \texttt{r}), das schreiben (write, \texttt{w}) und die Ausführung
(execution, \texttt{x}) vergeben. Damit die Datei für einen Benutzer wirklich
ausführbar ist, muß er das Lese- und das
Ausführungsrecht\index{Ausührungsrecht} haben. Um die Rechte zu setzen, muß man
\texttt{chmod} in Parametern mitgeben, worauf sich das Kommando bezieht, ob das
Recht gesetzt (\texttt{+}) oder weggenommen (\texttt{-}) werden soll, und
welche Rechte gemeint sind. Damit alle Benutzer das Skript ausführen dürfen,
benutzt man das Kommando \texttt{chmod ugo+rx name} oder einfach \texttt{chmod
+rx name}. Mit \texttt{chmod u+x name} hat nur der Besitzer der Datei
Ausführungsrechte.
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgründen auf den meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet, muß man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name} wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens \texttt{name} auszuführen.
Auf den meisten Systemen befindet sich im Pfad der Eintrag \texttt{\~{}/bin} bzw. \texttt{/home/benutzername/bin}, das bedeutet daß man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so daß sie auch ohne eine Pfadangabe gefunden werden. Wie der Pfad genau aussieht kann man an der Shell durch Eingabe von \texttt{echo \$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden.
\subsection{Rückgabewerte}\label{exitcode}\index{Rückgabewert|(textbf}\index{Exit-Code|see{Rückgabewert}}\index{Exit-Status|see{Rückgabewert}}
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. \texttt{grep}\index{grep=\texttt{grep}}) werden unterschiedliche Exit-Codes für unterschiedliche Ereignisse benutzt.
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 ab\-hän\-gen. Beispiele dazu sieht man bei der Beschreibung der Kommandos \texttt{if}\index{if=\texttt{if}} (\ref{if}), \texttt{case}\index{case=\texttt{case}} (\ref{case}), \texttt{while}\index{while=\texttt{while}} (\ref{while}) und \texttt{until}\index{until=\texttt{until}} (\ref{until}), sowie in dem Abschnitt über Befehlsformen (\ref{befehlsformen}).
In der Bourne-Shell wird der Exit-Code des letzten aufgerufenen Programms in der Variable \texttt{\$?}\index{\$?=\texttt{\$?}} abgelegt. Üblicherweise geben Programme den Wert 0 zurück, bei irgendwelchen Problemen einen von 0 verschiedenen Wert. Das wird im folgenden Beispiel deutlich:
\LTXtable{\textwidth}{tab_beisp_exitcode.tex}
Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann --- falls der Ausdruck erfolgreich war --- gelöscht wird:
\LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex}
Näheres zur Verknüpfung von Aufrufen steht im Kapitel über Befehlsformen (\ref{befehlsformen}). Beispiele zur Benutzung von Rückgabewerten in Schleifen finden sich im Anhang unter \ref{beisp_schleifen_exitcode}.
Auch Shell-Skripte können einen Rückgabewert an aufrufende Prozesse zurückgeben. Wie das geht, steht in dem Abschnitt zu \texttt{exit} (\ref{exit}).
\index{Rückgabewert|)}
\section{Variablen}\index{Variablen|(textbf}
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\index{Datentypen} wie Ganzzahlen, Fließkommazahlen oder Strings\footnote{Bei einigen modernen Shells (\texttt{csh}\index{C-Shell}, \texttt{tcsh}\index{TENEX-C-Shell}, \texttt{ksh}\index{Korn-Shell}, \texttt{bash}\index{Bourne-Again-Shell}, \texttt{zsh}\index{Z-Shell}...) hat man die Möglichkeit, Variablentypen zu vereinbaren. In der Bourne-Shell\index{Bourne-Shell} nicht.}. Alle Variablen werden als String gespeichert, wenn die Variable die Funktion einer Zahl übernehmen soll, dann muß das verarbeitende Programm die Variable entsprechend interpretieren\footnote{Für arithmetische Operationen steht das Programm \texttt{expr}\index{expr=\texttt{expr}} zur Verfügung (siehe Zählschleifen-Beispiel unter \ref{while})}.
Man muß bei der Benutzung von Variablen sehr aufpassen, wann die Variable expandiert\footnote{Mit \emph{Expansion}\index{Expansion} ist das Ersetzen des Variablennamens durch den Inhalt gemeint} wird und wann nicht. 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\index{Quoting} (siehe unter \ref{quoting}).
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 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.
Wenn man auf den Inhalt einer Variablen zugreifen möchte, leitet man den Variablennamen durch ein \texttt{\$}-Zeichen ein. Alles was mit einem \texttt{\$} anfängt wird von der Shell als Variable angesehen und entsprechend behandelt (expandiert).
\index{Variablen|)}
\section{Vordefinierte Variablen}\label{vordefinierte_variablen}\index{Variablen}\index{vordefinierte Variablen}
\index{\$n=\texttt{\$}$n$|(textbf}\index{\$*=\texttt{\$*}|(textbf}\index{\$@=\texttt{\$@}|(textbf}\index{\$\#=\texttt{\$\#}|(textbf}\index{\$?=\texttt{\$?}|(textbf}\index{\$\$=\texttt{\$\$}|(textbf}\index{\$!!=\texttt{\$!!}|(textbf}\index{\$ERRNO=\texttt{\$ERRNO}|(textbf}\index{\$PWD=\texttt{\$PWD}|(textbf}\index{\$OLDPWD=\texttt{\$OLDPWD}|(textbf}
\index{ERRNO=\texttt{ERRNO}|see{\$ERRNO}}\index{PWD=\texttt{PWD}|see{\$PWD}}\index{OLDPWD=\texttt{OLDPWD}|see{\$OLDPWD}}
Es gibt eine Reihe von vordefinierten Variablen, deren Benutzung ein wesentlicher Bestandteil des Shell-Programmierens ist.
Die wichtigsten eingebauten Shell-Variablen sind:\nopagebreak
\LTXtable{\textwidth}{tab_vordefinierte_variablen.tex}
\texttt{\$ERRNO}, \texttt{\$PWD} und \texttt{\$OLDPWD} werden nicht von jeder Shell gesetzt.
\index{\$n=\texttt{\$}$n$|)}\index{\$*=\texttt{\$*}|)}\index{\$@=\texttt{\$@}|)}\index{\$\#=\texttt{\$\#}|)}\index{\$?=\texttt{\$?}|)}\index{\$\$=\texttt{\$\$}|)}\index{\$!!=\texttt{\$!!}|)}\index{\$ERRNO=\texttt{\$ERRNO}|)}\index{\$PWD=\texttt{\$PWD}|)}\index{\$OLDPWD=\texttt{\$OLDPWD}|)}
\section{Variablen-Substitution}\index{Variablen>-Substitution|(textbf}\index{Substitution|see{Variablen-Subst.}}\index{Variablen|(textbf}
\index{!==\texttt{!=}|(textbf}\index{\$\{Variable\}=\texttt{\$\{}\textsl{Variable}\texttt{\}}|(textbf}\index{\$\{Variable:-Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}}|(textbf}\index{\$\{Variable:=Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}}|(textbf}\index{\$\{Variable:?Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}}|(textbf}\index{\$\{Variable:+Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}}|(textbf}
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 (\texttt{bash}\index{Bourne-Again-Shell}, \texttt{ksh}\index{Korn-Shell}) existieren sogar Möglichkeiten, auf Substrings von Variableninhalten zuzugreifen. In der Standard-Shell benutzt man für einfache Aufgaben üblicherweise Tools wie \texttt{cut}, \texttt{basename}\index{basename=\texttt{basename}} oder \texttt{dirname}; komplexe Bearbeitungen erledigt der Stream-Editor \texttt{sed}\index{sed=\texttt{sed}}. Einleitende Informationen dazu finden sich im Kapitel über die Mustererkennung (\ref{mustererkennung}).
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, muß die \textsl{Variable} einen Wert enthalten. \nopagebreak
\LTXtable{\textwidth}{tab_variablen_substitution.tex}
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_variablen_substitution.tex}
\index{!==\texttt{!=}|)}\index{\$\{Variable\}=\texttt{\$\{}\textsl{Variable}\texttt{\}}|)}\index{\$\{Variable:-Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}}|)}\index{\$\{Variable:=Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}}|)}\index{\$\{Variable:?Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}}|)}\index{\$\{Variable:+Wert\}=\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}}|)}
\index{Variablen>-Substitution|)}\index{Variablen|)}
\section{Quoting}\index{Quoting|(textbf}\label{quoting}
\index{Anführungszeichen|(textbf}\index{Ticks|(textbf}\index{Backslash|(textbf}\index{;=\texttt{;}|(textbf}\index{\&=\texttt{\&}|(textbf}\index{( )=\texttt{( )}|(textbf}\index{|=\texttt{|}|(textbf}\index{<=\texttt{<}|(textbf}\index{!>=\texttt{!>}|(textbf}\index{!>\&=\texttt{!>\&}|(textbf}\index{*=\texttt{*}|(textbf}\index{?=\texttt{?}|(textbf}\index{[ ]=\texttt{[ ]}|(textbf}\index{\~{}=\texttt{\~{}}|(textbf}\index{+=\texttt{+}|(textbf}\index{-=\texttt{-}|(textbf}\index{@=\texttt{@}|(textbf}\index{!!=\texttt{!!}|(textbf}\index{Backticks|(textbf}\index{\$=\texttt{\$}|(textbf}\index{[newline]=\texttt{[newline]}|(textbf}\index{[space]=\texttt{[space]}|(textbf}\index{[tab]=\texttt{[tab]}|(textbf}
\index{' '=\texttt{' '}|see{Ticks}}\index{` `=\texttt{` `}|see{Backticks}}\index{\dq~\dq=\texttt{\dq~\dq}|see{Anführungszeichen}}\index{\textbackslash=\texttt{\textbackslash}|see{Backslash}}
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, daß diese expandiert (ersetzt) werden.
Die folgenden Zeichen haben eine spezielle Bedeutung innerhalb der Shell:\nopagebreak
\LTXtable{\textwidth}{tab_quoting_sonderzeichen.tex}
Die folgenden Zeichen können zum Quoten verwendet werden:\nopagebreak
\LTXtable{\textwidth}{tab_quoting_zeichen.tex}
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_quoting.tex}
\index{Anführungszeichen|)}\index{Ticks|)}\index{Backslash|)}\index{;=\texttt{;}|)}\index{\&=\texttt{\&}|)}\index{( )=\texttt{( )}|)}\index{|=\texttt{|}|)}\index{<=\texttt{<}|)}\index{!>=\texttt{!>}|)}\index{!>\&=\texttt{!>\&}|)}\index{*=\texttt{*}|)}\index{?=\texttt{?}|)}\index{[ ]=\texttt{[ ]}|)}\index{\~{}=\texttt{\~{}}|)}\index{+=\texttt{+}|)}\index{-=\texttt{-}|)}\index{@=\texttt{@}|)}\index{!!=\texttt{!!}|)}\index{Backticks|)}\index{\$=\texttt{\$}|)}\index{[newline]=\texttt{[newline]}|)}\index{[space]=\texttt{[space]}|)}\index{[tab]=\texttt{[tab]}|)}
\index{Quoting|)}
\section{Meta-Zeichen}\index{Meta-Zeichen|(textbf}\index{Wildcards|see{Metazeichen}}\index{Joker-Zeichen|see{Metazeichen}}\index{Platzhalter|see{Metazeichen}}
\index{*=\texttt{*}|(textbf}\index{?=\texttt{?}|(textbf}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}|(textbf}\index{[a-q]=\texttt{[}\textsl{a}\texttt{-}\textsl{q}\texttt{]}|(textbf}\index{[!!abc]=\texttt{[!!}\textsl{abc}\texttt{]}|(textbf}\index{Dateinamen|(textbf}
\index{\~{}=\texttt{\~{}}|(textbf}\index{\~{}name=\texttt{\~{}}\textsl{name}|(textbf}\index{\~{}+=\texttt{\~{}+}|(textbf}\index{\~{}-=\texttt{\~{}-}|(textbf}
Bei der Angabe von Dateinamen können eine Reihe von Meta-Zeichen\footnote{Meta-Zeichen werden auch Wildcards, Joker-Zeichen oder Platzhalter genannt.} verwendet werden, um mehrere Dateien gleichzeitig anzusprechen oder um nicht den vollen Dateinamen ausschreiben zu müssen.
Die wichtigsten Meta-Zeichen sind:\nopagebreak
\LTXtable{\textwidth}{tab_metazeichen.tex}
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_metazeichen.tex}
\index{*=\texttt{*}|)}\index{?=\texttt{?}|)}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}|)}\index{[a-q]=\texttt{[}\textsl{a}\texttt{-}\textsl{q}\texttt{]}|)}\index{[!!abc]=\texttt{[!!}\textsl{abc}\texttt{]}|)}\index{Dateinamen|)}
\index{\~{}=\texttt{\~{}}|)}\index{\~{}name=\texttt{\~{}}\textsl{name}|)}\index{\~{}+=\texttt{\~{}+}|)}\index{\~{}-=\texttt{\~{}-}|)}
\index{Meta-Zeichen|)}
\section{Klammer-Expansion}
man bash
/Brace Expansion
TODO!!!
\section{Mustererkennung}\index{Mustererkennung|(textbf}\label{mustererkennung}
\index{ed=\texttt{ed}|(textbf}\index{ex=\texttt{ex}|(textbf}\index{vi=\texttt{vi}|(textbf}\index{sed=\texttt{sed}|(textbf}\index{awk=\texttt{awk}|(textbf}\index{grep=\texttt{grep}|(textbf}\index{egrep=\texttt{egrep}|(textbf}
\index{*=\texttt{*}|(textbf}\index{.=\texttt{.}|(textbf}\index{\^=\texttt{\^}|(textbf}\index{\$=\texttt{\$}|(textbf}\index{Backslash|(textbf}\index{[ ]=\texttt{[ ]}|(textbf}\index{\textbackslash( \textbackslash)=\texttt{\textbackslash( \textbackslash)}|(textbf}\index{\textbackslash\{ \textbackslash\}=\texttt{\textbackslash\{ \textbackslash\}}|(textbf}\index{\textbackslash< \textbackslash>=\texttt{\textbackslash< \textbackslash>}|(textbf}\index{+=\texttt{+}|(textbf}\index{?=\texttt{?}|(textbf}\index{|=\texttt{|}|(textbf}\index{( )=\texttt{( )}|(textbf}\index{Regulärer Ausdruck|(textbf}
\index{\textbackslash n=\texttt{\textbackslash}\textsl{n}|(textbf}\index{\&=\texttt{\&}|(textbf}\index{\~{}=\texttt{\~{}}|(textbf}\index{\textbackslash u=\texttt{\textbackslash u}|(textbf}\index{\textbackslash U=\texttt{\textbackslash U}|(textbf}\index{\textbackslash l=\texttt{\textbackslash l}|(textbf}\index{\textbackslash L=\texttt{\textbackslash L}|(textbf}\index{\textbackslash E=\texttt{\textbackslash E}|(textbf}\index{\textbackslash e=\texttt{\textbackslash e}|(textbf}
Man unterscheidet in der Shell-Programmierung zwischen den
Meta-Zeichen\index{Meta-Zeichen}, die bei der Bezeichnung von Dateinamen
eingesetzt werden (sogenanntes `Globbing'\index{Globbing}) und den Meta-Zeichen, die in
mehreren Programmen Verwendung finden, um z. B. Suchmuster zu definieren. Diese
Muster werden auch reguläre Ausdrücke (regular expression)\index{Regular
Expression|see{Regulärer Ausdruck}}\index{Expression|see{Regulärer
Ausdruck}}\index{Ausdruck|see{Regulärer Ausdruck}} genannt. Sie bieten
wesentlich mehr Möglichkeiten als die relativ einfachen Wildcards für
Dateinamen.
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur Verfügung stehen. Eine ausführlichere Beschreibung der Einträge findet sich auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
\LTXtable{\textwidth}{tab_mustererkennung_muster.tex}
Bei einigen Tools (\texttt{ex}, \texttt{sed} und \texttt{ed}) werden zwei Muster angegeben: Ein Suchmuster (links) und ein Ersatzmuster (rechts). Nur die folgenden Zeichen sind in einem Ersatzmuster gültig:\nopagebreak
\LTXtable{\textwidth}{tab_mustererkennung_ersatzmuster.tex}
\medskip\emph{Sonderzeichen in Suchmustern:}\label{beschreibung_der_muster}\nopagebreak
\LTXtable{\textwidth}{tab_mustererkennung_sonderzeichen.tex}
\medskip\emph{Sonderzeichen in Ersatzmustern:}\nopagebreak
\LTXtable{\textwidth}{tab_mustererkennung_ersatzsonderzeichen.tex}
\medskip\emph{Beispiele:} Muster\nopagebreak
\LTXtable{\textwidth}{tab_beisp_muster.tex}
\medskip\emph{Beispiele:} egrep- oder awk-Muster\nopagebreak
\LTXtable{\textwidth}{tab_beisp_muster_egrep.tex}
\medskip\emph{Beispiele:} ex- oder vi-Muster\nopagebreak
\LTXtable{\textwidth}{tab_beisp_muster_ex.tex}
\medskip\emph{Beispiele:} sed- oder grep-Muster\nopagebreak
\LTXtable{\textwidth}{tab_beisp_muster_sed.tex}
\medskip\emph{Beispiele:} Suchen und Ersetzen mit \texttt{sed} und \texttt{ex}. Im Folgenden werden Leerzeichen durch \Ovalbox{SPACE} und Tabulatoren durch \Ovalbox{TAB} gekennzeichnet. Befehle für ex werden mit einem Doppelpunkt eingeleitet.\nopagebreak
\LTXtable{\textwidth}{tab_beisp_sed-ex.tex}
\index{ed=\texttt{ed}|)}\index{ex=\texttt{ex}|)}\index{vi=\texttt{vi}|)}\index{sed=\texttt{sed}|)}\index{awk=\texttt{awk}|)}\index{grep=\texttt{grep}|)}\index{egrep=\texttt{egrep}|)}
\index{*=\texttt{*}|)}\index{.=\texttt{.}|)}\index{\^=\texttt{\^}|)}\index{\$=\texttt{\$}|)}\index{Backslash|)}\index{[ ]=\texttt{[ ]}|)}\index{\textbackslash( \textbackslash)=\texttt{\textbackslash( \textbackslash)}|)}\index{\textbackslash\{ \textbackslash\}=\texttt{\textbackslash\{ \textbackslash\}}|)}\index{\textbackslash< \textbackslash>=\texttt{\textbackslash< \textbackslash>}|)}\index{+=\texttt{+}|)}\index{?=\texttt{?}|)}\index{|=\texttt{|}|)}\index{( )=\texttt{( )}|)}\index{Regulärer Ausdruck|)}
\index{\textbackslash n=\texttt{\textbackslash}\textsl{n}|)}\index{\&=\texttt{\&}|)}\index{\~{}=\texttt{\~{}}|)}\index{\textbackslash u=\texttt{\textbackslash u}|)}\index{\textbackslash U=\texttt{\textbackslash U}|)}\index{\textbackslash l=\texttt{\textbackslash l}|)}\index{\textbackslash L=\texttt{\textbackslash L}|)}\index{\textbackslash E=\texttt{\textbackslash E}|)}\index{\textbackslash e=\texttt{\textbackslash e}|)}
\index{Mustererkennung|)}
\section{Programmablaufkontrolle}
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.\nopagebreak
\subsection{Kommentare\label{kommentare}\index{Kommentar|(textbf} (\texttt{\#})}\index{\#=\texttt{\#}|see{Kommentar}}
Kommentare in der Shell beginnen immer mit dem Nummern-Zeichen (\verb\#\). Dabei spielt es keine Rolle, ob das Zeichen am Anfang der Zeile steht, oder hinter irgendwelchen Befehlen. Alles von diesem Zeichen bis zum Zeilenende wird nicht beachtet (bis auf eine Ausnahme --- siehe unter \ref{auswahl_der_shell}).
\index{Kommentar|)}
\subsection{Auswahl der Shell (\texttt{\#!})}\label{auswahl_der_shell}\index{\#!!=\texttt{\#!!}|see{Shell / Auswahl der\ldots}}\index{Shell>Auswahl der\ldots|(textbf}
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\index{Subshell} und führt das restliche Skript in dieser aus.
Die Angabe erfolgt über eine Zeile in der Form \verb\#!/bin/sh\, wobei unter \verb\/bin/sh\ die entsprechende Shell (in diesem Fall die Bourne-Shell) liegt. Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile des Skripts steht.
\index{Shell>Auswahl der\ldots|)}
\subsection{Null-Befehl (\texttt{:})}\label{null-befehl}\index{Null-Befehl|(textbf}\index{:=\texttt{:}|see{Null-Befehl}}\index{Doppelpunkt|see{Null-Befehl}}
Dieser Befehl tut nichts, außer den Status 0 zurückzugeben. Er wird benutzt, um Endlosschleifen\index{Endlosschleife} zu schreiben (siehe unter \ref{while}), oder um leere Blöcke in \texttt{if}- oder \texttt{case}-Konstrukten\index{if=\texttt{if}}\index{case=\texttt{case}} möglich zu machen.
\medskip\emph{Beispiel:} Prüfen, ob jemand angemeldet ist:\nopagebreak
\LTXtable{\textwidth}{tab_beisp_nullbefehl.tex}
\index{Null-Befehl|)}
\subsection{Source (\texttt{.})}\label{source}\index{source=\texttt{source}|(textbf}\index{.=\texttt{.}|see{source}}
Ein Shell-Skript kann in keiner Weise Einfluß auf die umgebende Shell nehmen. Das heißt, daß es beispielsweise nicht möglich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verfügung stehen. Genauso wenig ist es möglich, daß ein Skript den Pfad ändert, in dem man sich befindet. Der Grund für dieses Verhalten ist die Systemsicherheit. Man will verhindern, daß ein Skript unbemerkt Änderungen an der Benutzerumgebung vornimmt.
Wenn es aber doch gewünscht wird, daß ein Skript die Umgebung des Benutzers ändern kann, dann muß es mit dem Source-Kommando aufgerufen werden. Das wird in der Form \verb\source skriptname\ bzw. \verb\. skriptname\ angegeben. Er bewirkt ähnliches wie ein \verb\#include\ in der Programmiersprache C.
Die `gesourcte' Datei wird eingelesen und ausgeführt, als ob ihr Inhalt an der Stelle des Befehls stehen würde. Diese Methode wird zum Beispiel beim Login in den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\) oder 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~\ref{init-skript}).
\index{source=\texttt{source}|)}
\subsection{Funktionen}\index{Funktion|(textbf}
Es ist in der Shell auch möglich, ähnlich wie in einer `richtigen' Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die Bourne-Shell (\verb\sh\) nicht über Aliase\index{Aliase} verfügt, können einfache Funktionen als Ersatz dienen.
Der Rückgabewert einer Funktion ist gleich dem Rückgabewert des letzten in der Funktion aufgerufenen Kommandos.
\medskip\emph{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 \verb\count\.\nopagebreak
\LTXtable{\textwidth}{tab_beisp_funktionen.tex}
\index{Funktion|)}
\subsection{Bedingungen (\texttt{[ ]})}\label{bedingungen}\index{Bedingungen|see{test}}\index{[ ]=\texttt{[ ]}|see{test}}\index{test=\texttt{test}|(textbf}
Da die Standard-Shell keine arithmetischen oder logischen Ausdrücke auswerten kann\footnote{\texttt{if} und Konsorten prüfen nur den Rückgabewert\index{Rückgabewert} eines aufgerufenen Programmes --- 0 bedeutet `true', alles andere bedeutet `false', siehe auch \ref{exitcode}.}, muß dazu ein externes Programm benutzt werden. Dieses Programm heißt \verb\test\\index{test=\texttt{test}}. Üblicherweise besteht auf allen Systemen auch noch ein Link namens \verb\[\ auf dieses Programm. Dieser Link ist fast absolut gleichwertig zu benutzen (in dieser Form wird allerdings eine abschließende Klammer nach der Bedingung erwartet). Dementsprechend ist es auch zwingend erforderlich, nach der Klammer ein Leerzeichen zu schreiben. Das dient dazu, Bedingungen in \verb\if\-Abfragen u. ä. lesbarer zu machen.
Das \verb\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.
\medskip\medskip\emph{Dateitests:}\index{Dateitests}\nopagebreak
\LTXtable{\textwidth}{tab_bedingungen_dateitests.tex}
\medskip\emph{Bedingungen für Zeichenfolgen:}\nopagebreak
\LTXtable{\textwidth}{tab_bedingungen_zeichenfolgen.tex}
\medskip\emph{Ganzzahlvergleiche:}\nopagebreak
\LTXtable{\textwidth}{tab_bedingungen_ganzzahlvergleiche.tex}
\medskip\emph{Kombinierte Formen:}\nopagebreak
\LTXtable{\textwidth}{tab_bedingungen_kombinationen.tex}
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_bedingungen.tex}
\index{test=\texttt{test}|)}
\subsection{if\ldots}\label{if}\index{if=\texttt{if}|(textbf}\index{then=\texttt{then}|see{if}}\index{elif=\texttt{elif}|see{if}}\index{else=\texttt{else}|see{if}}\index{fi=\texttt{fi}|see{if}}
Die \texttt{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.
Die Syntax der \texttt{if}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_if.tex}
Wenn die \textsl{Bedingung1} erfüllt ist, werden die \textsl{Befehle1} ausgeführt; andernfalls, wenn die \textsl{Bedingung2} erfüllt ist, werden die \textsl{Befehle2} ausgeführt. Trifft keine Bedingung zu, sollen die \textsl{Befehle3} ausgeführt werden.
Bedingungen werden normalerweise mit dem Befehl \texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen}) formuliert. Es kann aber auch der Rückgabewert\footnote{Siehe unter \ref{exitcode}.}\index{Rückgabewert} jedes anderen Kommandos ausgewertet werden. Für Bedingungen, die auf jeden Fall zutreffen sollen steht der Null-Befehl (\texttt{:}, siehe unter \ref{null-befehl}) zur Verfügung.
\medskip\emph{Beispiele:} Man achte auf die Positionierung der Semikola\footnote{Und man verzeihe mir einen eventuell falschen Plural\ldots :-)}.\nopagebreak
\LTXtable{\textwidth}{tab_beisp_if.tex}
\index{if=\texttt{if}|)}
\subsection{case\ldots}\label{case}\index{case=\texttt{case}|(textbf}\index{esac=\texttt{esac}|see{case}}
\index{;;=\texttt{;;}|see{case}}
Auch die \texttt{case}-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden. Sie dient, ähnlich wie die \texttt{if}-Anweisung zur Fallunterscheidung\index{Fallunterscheidung|see{case}}\index{Fallunterscheidung|see{if}}. Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden (Entweder / Oder), sondern es sind mehrere Fälle möglich. Man kann die \texttt{case}-Anweisung auch durch eine geschachtelte \texttt{if}-Anweisung völlig umgehen, allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten.
Die Syntax der \texttt{case}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_case.tex}
Wenn der \textsl{Wert} mit dem \textsl{Muster1} übereinstimmt, wird die entsprechende Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle1}) ausgeführt, bei Übereinstimmung mit \textsl{Muster2} werden die Kommandos der zweiten Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle2}) ausgeführt, usw. Der letzte Befehl in jeder Gruppe muß mit \texttt{;;} gekennzeichnet werden. Das bedeutet für die Shell soviel wie `springe zum nächsten \texttt{esac}', so daß die anderen Bedingungen nicht mehr überprüft werden.
In den Mustern sind die gleichen Meta-Zeichen\index{Meta-Zeichen} erlaubt wie bei der Auswahl von Dateinamen. Das bedeutet, daß man durch ein einfaches \texttt{*}\index{*=\texttt{*}} den Default-Pfad kennzeichnen kann. Dieser wird dann durchlaufen, wenn kein anderes Muster zutrifft. Wenn in einer Zeile mehrere Muster angegeben werden sollen, müssen sie durch ein Pipezeichen (\texttt{|}, logisches ODER) getrennt werden.
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_case.tex}
\index{case=\texttt{case}|)}
\subsection{for\ldots}\label{for}\index{for=\texttt{for}|(textbf}\index{Schleife>for-=\texttt{for}-|see{for}}\index{in=\texttt{in}|see{for}}\index{in=\texttt{in}|see{case}}\index{do=\texttt{do}|see{for}}\index{do=\texttt{do}|see{while}}\index{do=\texttt{do}|see{until}}\index{do=\texttt{done}|see{for}}\index{do=\texttt{done}|see{while}}\index{do=\texttt{done}|see{until}}
Dieses Konstrukt ähnelt nur auf den ersten Blick seinen Pendants aus anderen Programmiersprachen. In anderen Sprachen wird die \texttt{for}-Schleife meistens dazu benutzt, eine Zählvariable über einen bestimmten Wertebereich iterieren zu lassen (\texttt{for i = 1 to 100\ldots next}). In der Shell dagegen wird die Laufvariable nicht mit aufeinanderfolgenden Zahlen belegt, sondern mit einzelnen Werten aus einer anzugebenden Liste\footnote{Wenn man trotzdem eine Laufvariable\index{Laufvariable} braucht, muß man dazu die \texttt{while}-Schleife\index{while=\texttt{while}} `mißbrauchen' (siehe unter \ref{while}).}.
Die Syntax der \texttt{for}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_for.tex}
Die \textsl{Befehle} werden ausgeführt, wobei der Variablen \textsl{x} nacheinander die Werte aus der \textsl{Liste} zugewiesen werden. Wie man sieht ist die Angabe der \textsl{Liste} optional, wenn sie nicht angegeben wird, nimmt \textsl{x} der Reihe nach alle Werte aus \texttt{\$@} (in dieser vordefinierten Variablen liegen die Aufrufparameter --- siehe unter \ref{vordefinierte_variablen}) an. Wenn die Ausführung eines Schleifendurchlaufs bzw der ganzen Schleife abgebrochen werden soll, müssen die Kommandos \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_for.tex}
\index{for=\texttt{for}|)}
\subsection{while\ldots}\label{while}\index{while=\texttt{while}|(textbf}\index{Schleife>while-=\texttt{while}-|see{while}}\index{Schleife>Fußgesteuerte-|see{while}}\index{Fußgesteuerte Schleife|see{while}}
Die \texttt{while}-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist: die Kopfgesteuerte Schleife.
Die Syntax der \texttt{while}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_while.tex}
Die \textsl{Befehle} werden so lange ausgeführt, wie die \textsl{Bedingung} erfüllt ist. Dabei wird die \textsl{Bedingung} vor der Ausführung der \textsl{Befehle} überprüft. Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der \texttt{if}-Anweisung, mit mit dem Befehl \texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen}) formuliert. Wenn die Ausführung eines Schleifendurchlaufs bzw der ganzen Schleife abgebrochen werden soll, müssen die Kommandos \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiel:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_while.tex}
Eine Standard-Anwendung der \texttt{while}-Schleife ist der Ersatz für die
Zählschleife\index{Zählschleife}\index{Schleife>Zähl-=Zähl-|see{Zählschleife}}.
In anderen Sprachen kann man mit der
\texttt{for}-Schleife\index{for=\texttt{for}} eine
Laufvariable\index{Laufvariable} über einen bestimmten Wertebereich iterieren
lassen (\texttt{for i = 1 to 100...next}). Da das mit der \texttt{for}-Schleife
der Shell nicht geht\footnote{Auf einigen Systemen steht für diesen Zweck auch
das Kommando \texttt{seq}\index{seq=\texttt{seq}} zur Verfügung.},
ersetzt man die Funktion durch geschickte Anwendung der
\texttt{while}-Schleife:\nopagebreak
\LTXtable{\textwidth}{tab_beisp_while_for.tex}
\index{while=\texttt{while}|)}
\subsection{until\ldots}\label{until}\index{until=\texttt{until}|(textbf}\index{Schleife>until-=\texttt{until}-|see{until}}\index{Schleife>Kopfgesteuerte-|see{until}}\index{Kopfgesteuerte Schleife|see{until}}
Die \texttt{until}-Schleife ist das Gegenstück zur \texttt{while}-Schleife: die ebenfalls aus vielen anderen Sprachen bekannte Fußgesteuerte Schleife.
Die Syntax der \texttt{until}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_until.tex}
Die \textsl{Befehle} werden ausgeführt, bis die \textsl{Bedingung} erfüllt ist. Dabei wird die \textsl{Bedingung} nach der Ausführung der \textsl{Befehle} überprüft. Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der \texttt{if}-Anweisung, mit mit dem Befehl \texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen}) formuliert. Wenn die Ausführung eines Schleifendurchlaufs bzw der ganzen Schleife abgebrochen werden soll, müssen die Kommandos \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiel:} Hier wird die Bedingung nicht per \texttt{test} sondern mit dem Rückgabewert\index{Rückgabewert} des Programms \texttt{grep}\index{grep=\texttt{grep}} formuliert.\nopagebreak
\LTXtable{\textwidth}{tab_beisp_until.tex}
\index{until=\texttt{until}|)}
\subsection{continue}\label{continue}\index{continue=\texttt{continue}|(textbf}
Die Syntax der \texttt{continue}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_continue.tex}
Man benutzt \texttt{continue} um die restlichen Befehle in einer Schleife zu überspringen und mit dem nächsten Schleifendurchlauf anzufangen. Wenn der Parameter \textsl{n} angegeben wird, werden \textsl{n} Schleifenebenen übersprungen.
\index{continue=\texttt{continue}|)}
\subsection{break}\label{break}\index{break=\texttt{break}|(textbf}
Die Syntax der \texttt{break}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_break.tex}
Mit \texttt{break} kann man die innerste Ebene (bzw. \textsl{n} Schleifenebenen) verlassen ohne den Rest der Schleife auszuführen.
\index{break=\texttt{break}|)}
\subsection{exit}\label{exit}\index{exit=\texttt{exit}|(textbf}
Die Syntax der \texttt{exit}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_exit.tex}
Die \texttt{exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Parameter \textsl{n} angegeben wird, wird er von dem Skript als Exit-Code zurückgegeben.
\index{exit=\texttt{exit}|)}
\section{Befehlsformen}\label{befehlsformen}\index{Befehls>-formen|(textbf}
\index{\&=\texttt{\&}|(textbf}\index{;=\texttt{;}|(textbf}\index{( )=\texttt{( )}|(textbf}\index{\{ \}=\texttt{\{ \}}|(textbf}\index{Pipe|(textbf}\index{Backticks|(textbf}\index{\&\&=\texttt{\&\&}|(textbf}\index{!|!|=\texttt{!|!|}|(textbf}\index{Befehls>-substitution|(textbf}\index{Befehls>-folge|(textbf}\index{Befehls>-block|(textbf}
\index{!|=\texttt{!|}|see{Pipe}}\index{Substitution|see{Befehls-Subst.}}
Es gibt eine Reihe verschiedener Möglichkeiten, Kommandos auszuführen:\nopagebreak
\LTXtable{\textwidth}{tab_befehlsformen.tex}
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_befehlsformen.tex}
\index{\&=\texttt{\&}|)}\index{;=\texttt{;}|)}\index{( )=\texttt{( )}|)}\index{\{ \}=\texttt{\{ \}}|)}\index{Pipe|)}\index{Backticks|)}\index{\&\&=\texttt{\&\&}|)}\index{!|!|=\texttt{!|!|}|)}\index{Befehls>-substitution|)}\index{Befehls>-folge|)}\index{Befehls>-block|)}
\index{Befehls>-formen|)}
\section{Datenströme}\label{datenstrom}\index{Datenströme|(textbf}
\index{<=\texttt{<}|(textbf}\index{<<=\texttt{<<}|(textbf}\index{!>\&=\texttt{!>\&}|(textbf}\index{!>\&-=\texttt{!>\&-}|(textbf}\index{<\&=\texttt{<\&}|(textbf}\index{<\&-=\texttt{<\&-}|(textbf}\index{!>=\texttt{!>}|(textbf}\index{!>!>=\texttt{!>!>}|(textbf}\index{Pipe|(textbf}\index{Dateideskriptor|(textbf}\index{Standard-Eingabe|(textbf}\index{Standard-Ausgabe|(textbf}\index{Standard-Fehlerausgabe|(textbf}\index{Here-Dokument|(textbf}
\index{Deskriptor|see{Dateideskriptor}}\index{Ausgabe|see{Standard-Ausgabe}}\index{Fehlerausgabe|see{Standard-Fehlerausgabe}}\index{Fehlermeldungen|see{Standard-Fehlerausgabe}}\index{stdin|see{Standard-Eingabe}}\index{stdout|see{Standard-Ausgabe}}\index{stderr|see{Standard-Fehlerausgabe}}
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 Standard-Eingabe entgegenzunehmen und Ausgaben dementsprechend auf der Standard-Ausgabe zu machen. Es gibt noch einen dritten Kanal für Fehlermeldungen, so daß man eine einfache Möglichkeit hat, fehlerhafte Programmdurchläufe zu behandeln indem man die Fehlermeldungen von den restlichen Ausgaben trennt.
Es folgt eine Aufstellung der drei Standardkanäle:\nopagebreak
\LTXtable{\textwidth}{tab_datenstroeme_kanaele.tex}
Die standardmäßige Eingabequelle oder das Ausgabeziel können wie folgt geändert werden:
\emph{Einfache Umlenkung:}\nopagebreak\index{Umlenkung}
\LTXtable{\textwidth}{tab_datenstroeme_einfach.tex}
Die Technik eines Here-Dokuments ist sicherlich auf den ersten Blick etwas
verwirrend. Man benutzt Here-Dokumente zum Beispiel in einer Situation, in der
ein fest vorgegebener Text benötigt wird. Man stelle sich ein Skript vor, das
jeden Tag eine Mail mit festem Inhalt und variablem Anhang verschickt.
Oder eine eingebaute Hilfe-Funktion, die bei falschen Parametern einen
Hilfetext ausgibt.
Natürlich könnte man zu diesem Zweck eine eigene Datei einrichten, aber das ist
eigentlich nicht notwendig. Man handelt sich nur Ärger ein, wenn man das Skript
auf einen anderen Rechner portiert und die Datei vergißt. Abgesehen davon - wo
legt man eine solche Datei sinnvoll ab?
Um diesem Ärger zu entgehen, sollte man in einer solchen Situation ein
Here-Dokument benutzen.
\emph{Umlenkung mit Hilfe von Dateideskriptoren:}\nopagebreak
\LTXtable{\textwidth}{tab_datenstroeme_deskriptoren.tex}
\emph{Mehrfach-Umlenkung:}\index{Umlenkung}\index{Mehrfach-Umlenkung}\nopagebreak
\LTXtable{\textwidth}{tab_datenstroeme_mehrfach.tex}
Zwischen den Dateideskriptoren und einem Umlenkungssymbol darf kein Leerzeichen sein; in anderen Fällen sind Leerzeichen erlaubt.
\medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_datenstroeme.tex}
\medskip\emph{Beispiel eines Here-Dokuments:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_datenstroeme_here-dokument.tex}
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:\nopagebreak
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, daß die TOC (Table Of Contents) der CD in die Datei 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 `cdparanoia' ausgelesen. Da kein Dateiname angegeben wird, schreibt cdparanoia die Daten auf seine Standard-Ausgabe. Diese wird von dem Brennprogramm `cdrdao' übernommen und in Verbindung mit der TOC `on the fly' auf die CD geschrieben.\label{cdrdao}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_datenstroeme_cdparanoia.tex}
\index{<=\texttt{<}|)}\index{!>\&=\texttt{!>\&}|)}\index{!>\&-=\texttt{!>\&-}|)}\index{<\&=\texttt{<\&}|)}\index{<\&-=\texttt{<\&-}|)}\index{!>=\texttt{!>}|)}\index{!>!>=\texttt{!>!>}|)}\index{Pipe|)}\index{Dateideskriptor|)}\index{Standard-Eingabe|)}\index{Standard-Ausgabe|)}\index{Standard-Fehlerausgabe|)}
\index{Datenströme|)}

View File

@ -0,0 +1,34 @@
\chapter{Wo sind Unterschiede zu DOS-Batchdateien?}\index{DOS|(textbf}\index{Batchdateien|(textbf}
Unter DOS werden Batchdateien 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
Shell-Aliasen\index{Aliase} oder Shell-Funktionen.\bigskip
Shell-Skripte können viel mehr als Batchdateien.\bigskip
Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von
Anweisungen, die nacheinander ausgeführt werden. Es stehen zwar auch einige
einfache Mechanismen zur Verzweigung zu Verfügung, aber das entspricht bei
weitem nicht den Möglichkeiten, die man an der Shell hat.
Interaktive Batchdateien sind unter DOS nicht möglich, in der Shell steht dazu
das \texttt{read}-Kommando zur Verfügung. Ein Mechanismus wie die
Befehls-Substitution\footnote{Verarbeitung der Ausgabe von Kommandos mittels
Backticks (siehe unter Befehlsformen - \ref{befehlsformen})} fehlt völlig.
Ein weiteres interessantes Merkmal ist die Behandlung von Pipes. Es ist unter
DOS zwar möglich, zwei Kommandos durch eine Pipe zu verbinden. Aber da es unter
DOS keine Möglichkeit gibt, zwei Kommandos parallel laufen zu lassen, wird das
erste Kommando vollständig ausgeführt, seine Ausgabe in eine temporäre Datei
geschrieben und danach als Eingabe für das zweite Kommando benutzt. Daß so ein
Verhalten unter Umständen schnell zu einer vollen Festplatte führen kann, sieht
man bei dem Beispiel, in dem eine CD kopiert werden soll (Kapitel \ref{cdrdao},
Seite \pageref{cdrdao}).
Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache
vergleichen. Es stehen alle Konstrukte zur Verfügung, die eine
Programmiersprache auszeichnen (Funktionen, Schleifen, Fallunterscheidungen,
Variablen, etc).
\index{DOS|)}\index{Batchdateien|)}

View File

@ -0,0 +1,18 @@
\chapter{Wofür Shell-Programmierung?}
Shell-Skripte werden im Wesentlichen aus zwei Gründen geschrieben: Erstens,
weil man so ständig wiederkehrende Kommandos zusammenfassen kann, die man dann
mit einem einfachen Aufruf starten kann, und zweitens, weil man so einfache
Programme schreiben kann, die relativ intelligent Aufgaben erledigen können.
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, daß
dieses Skript in regelmäßigen Abständen aufgerufen wird (per
Cron-Job\index{Cron-Job}).
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, sollte das Brennprogramm nur dann
aufrufen, wenn der Einlesevorgang erfolgreich abgeschlossen wurde.