Viele Aenderungen, Tabellen durch Syntax-Boxen ausgetauscht, neues Kapitel: date
This commit is contained in:
parent
68d30297e6
commit
82d1e3e470
@ -37,7 +37,9 @@ 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:
|
||||
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:
|
||||
|
||||
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
|
||||
\begin{lstlisting}
|
||||
@ -48,7 +50,67 @@ done
|
||||
echo "Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!"
|
||||
\end{lstlisting}
|
||||
|
||||
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.
|
||||
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{Subshell-Schleifen vermeiden}\label{subshellschleifen}
|
||||
|
||||
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
|
||||
zählt, wie viele Benutzer eine UID kleiner als 100 haben.
|
||||
|
||||
Folgendes Skript funktioniert nicht:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
cat /etc/passwd | while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Was ist passiert?
|
||||
|
||||
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
|
||||
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
|
||||
diese Pipe an eine Schleife übergibt. Das \texttt{read}-Kommando in der
|
||||
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bißchen Auswertung.
|
||||
|
||||
Es ist zu beobachten, daß bei der Ausgabe in Zeile 7 die Variable
|
||||
\texttt{\$count} korrekte Werte enthält. Um so unverständlicher ist es, daß sie
|
||||
nach der Vollendung der Schleife wieder den Wert 0 enthält.
|
||||
|
||||
Das liegt daran, daß diese Schleife als Teil einer Pipe in einer Subshell
|
||||
ausgeführt wird. Die Variable \texttt{\$count} steht damit in der Schleife
|
||||
praktisch nur lokal zur Verfügung, sie wird nicht an das umgebende Skript
|
||||
`hochgereicht'.
|
||||
|
||||
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
|
||||
einfachere Lösung an:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done < /etc/passwd
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
|
||||
in einer Subshell ausgeführt. Man kann auf das \texttt{cat}-Kommando verzichten
|
||||
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
|
||||
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
|
||||
|
||||
|
||||
\section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript}
|
||||
@ -248,7 +310,7 @@ echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
|
||||
\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
|
||||
(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
|
||||
@ -342,7 +404,7 @@ der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
|
||||
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
|
||||
bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses
|
||||
Problem für uns eine Herausforderung darstellt\footnote{Denn schließlich hat
|
||||
mpg123 schon von Hause aus eine Random-Funktion}, wollen wir vor dem Abspielen
|
||||
mpg123 schon von Hause aus eine Random-Funktion.}, wollen wir vor dem Abspielen
|
||||
der jeweiligen Datei etwas mit dem Dateinamen anstellen. Ob das eine einfache
|
||||
Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf
|
||||
einem externen Display angezeigt werden soll ist an dieser Stelle egal.
|
||||
@ -452,7 +514,7 @@ Ausgabe von \texttt{ps} erscheint das \texttt{grep}-Kommando allerdings mit
|
||||
|
||||
\subsection{Dateiinhalte suchen}\label{beispiele_suchen_dateien}\index{find=\texttt{find}|(textbf}
|
||||
|
||||
Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find} ist
|
||||
Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find}, ist
|
||||
folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen,
|
||||
überall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in
|
||||
denen eine Zeile mit dem Inhalt `strict' vorkommt. Man könnte jetzt
|
||||
@ -468,10 +530,10 @@ alle Dateien, die dem Muster entsprechen:
|
||||
|
||||
\lstinline|grep -r strict *.pl|
|
||||
|
||||
Das führt wieder nicht zu dem gewünschten Ergebnis. Da die Unterverzeichnisse
|
||||
nicht die Extension `*.pl' tragen, werden sie nicht berücksichtigt. Für die
|
||||
Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt
|
||||
\ref{find}) heran:
|
||||
Und wieder führt es nicht zu dem gewünschten Ergebnis. Da die
|
||||
Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
|
||||
berücksichtigt. Für die Suche in Unterverzeichnissen ziehen wir \texttt{find}
|
||||
(Siehe Abschnitt \ref{find}) heran:
|
||||
|
||||
\lstinline|find . -name \*.pl -exec grep strict {} \;|
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
\item Von DOS nach Linux HOWTO (\href{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
|
||||
\item Bash Guide for Beginners (\href{http://tldp.org/LDP/Bash-Beginners-Guide/}{http://tldp.org/LDP/Bash-Beginners-Guide/})
|
||||
\item Advanced Bash-Scripting Guide (\href{http://tldp.org/LDP/abs/}{http://tldp.org/LDP/abs/})
|
||||
\item The Open Group Base Specifications
|
||||
\item Single Unix Specifications V2
|
||||
\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}
|
||||
|
@ -195,74 +195,24 @@ sechs Kilobytes~--~
|
||||
|
||||
Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genießen.
|
||||
Bei der ersten führt jede zusätzliche oder gelöschte Zeile zu einer kaputten
|
||||
Ausgabedatei, bei der zweiten reichen schon einzelne Zeilen. In jedem Fall
|
||||
Ausgabedatei, bei der zweiten reichen schon einzelne Zeichen. In jedem Fall
|
||||
sollte nach dem Auspacken noch einmal mittels \texttt{sum} oder \texttt{md5sum}
|
||||
eine Checksumme gezogen und verglichen werden.
|
||||
|
||||
\section{Dateien, die es nicht gibt}
|
||||
|
||||
TODO!!! Dateien, die es nicht gibt
|
||||
Eine Eigenart der Behandlung von Dateien unter Unix besteht im Verhalten beim
|
||||
Löschen. Gelöscht wird nämlich zunächst nur der Inode, also die Markierung im
|
||||
Dateisystem unter der die Datei gefunden werden kann. Physikalisch besteht die
|
||||
Datei noch, sie wird lediglich im Verzeichnis nicht mehr angezeigt.
|
||||
|
||||
\subsection{Speichern in nicht existente Dateien}
|
||||
Hat ein Prozeß die Datei noch in irgendeiner Form geöffnet, kann er weiter
|
||||
darauf zugreifen. Erst wenn er die Datei schließt ist sie tatsächlich und
|
||||
unwiederbringlich `weg'.
|
||||
|
||||
TODO!!! Speichern in nicht existente Dateien
|
||||
Dieser Effekt der `nicht existenten Dateien' läßt sich an verschiedenen Stellen
|
||||
geschickt einsetzen.
|
||||
|
||||
\subsection{Subshell-Schleifen vermeiden}\label{subshellschleifen}
|
||||
|
||||
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
|
||||
zählt, wie viele Benutzer eine UID kleiner als 100 haben.
|
||||
|
||||
Folgendes Skript funktioniert nicht:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
cat /etc/passwd | while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Was ist passiert?
|
||||
|
||||
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
|
||||
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
|
||||
diese Pipe an eine Schleife übergibt. Das \texttt{read}-Kommando in der
|
||||
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bißchen Auswertung.
|
||||
|
||||
Es ist zu beobachten, daß bei der Ausgabe in Zeile 7 die Variable
|
||||
\texttt{\$count} korrekte Werte enthält. Um so unverständlicher ist es, daß sie
|
||||
nach der Vollendung der Schleife wieder den Wert 0 enthält.
|
||||
|
||||
Das liegt daran, daß diese Schleife als Teil einer Pipe in einer Subshell
|
||||
ausgeführt wird. Die Variable \texttt{\$count} steht damit in der Schleife
|
||||
praktisch nur lokal zur Verfügung, sie wird nicht an das umgebende Skript
|
||||
`hochgereicht'.
|
||||
|
||||
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
|
||||
einfachere Lösung an:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done < /etc/passwd
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
|
||||
in einer Subshell ausgeführt. Man kann auf das \texttt{cat}-Kommando verzichten
|
||||
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
|
||||
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
|
||||
|
||||
\subsection{Daten aus einer Subshell hochreichen}\label{daten_hochreichen}
|
||||
|
||||
@ -297,7 +247,7 @@ geht man in solchen F
|
||||
Bei einfachen Zahlenwerten könnte beispielsweise ein Rückgabewert helfen.
|
||||
Komplexere Informationen können in eine temporäre Datei geschrieben werden, die
|
||||
danach geparst werden müßte. Wenn die Informationen in Zeilen der Form
|
||||
`VARIABLE=\dq{}Wert\dq{}' gespeichert werden, kann die Datei einfach mittels
|
||||
\lstinline|VARIABLE="Wert"| gespeichert werden, kann die Datei einfach mittels
|
||||
\texttt{source} (Abschnitt \ref{source}) oder einem Konstrukt der Art
|
||||
\texttt{eval `cat tempfile`} gelesen werden.
|
||||
|
||||
|
60
shell.tex
60
shell.tex
@ -15,7 +15,7 @@
|
||||
headsepline, % Trennlinie unter die Kopfzeile
|
||||
pointlessnumbers, % Keine Punkte hinter den
|
||||
% Gliederungsnummern
|
||||
% halfparskip, % Abstände zwischen den Absätzen, statt
|
||||
halfparskip, % Abstände zwischen den Absätzen, statt
|
||||
% Einrückung der ersten Zeile
|
||||
% draft, % Entwurfsmodus
|
||||
final, % Release-Modus
|
||||
@ -51,10 +51,8 @@
|
||||
\lstset{
|
||||
extendedchars=true,
|
||||
backgroundcolor=\color[gray]{0.95},
|
||||
%basicstyle=\ttfamily\scriptsize,
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
numbers=left,
|
||||
%numberstyle=\tiny,
|
||||
numberstyle=\scriptsize,
|
||||
stepnumber=2,
|
||||
numbersep=5pt
|
||||
@ -93,12 +91,13 @@
|
||||
|
||||
\begin{document} % hiermit muß jedes Dokument beginnen
|
||||
|
||||
\vspace*{.75in} % Die Titelseite
|
||||
\vspace*{.6in} % Die Titelseite
|
||||
\thispagestyle{empty}
|
||||
\begin{centering}
|
||||
\rule{5in}{.04in}\\ \vspace{.25in}
|
||||
\Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in}
|
||||
\rule{5in}{.04in}\\ \vspace{.5in}
|
||||
\rule{5in}{.04in}\\ \vspace{.6in}
|
||||
\large v2.0.0 RC1\\
|
||||
\large \today\\ \vspace{.75in}
|
||||
\large von\\ \vspace{.3in}
|
||||
\LARGE {\bf Ronald Schaten} \\ \vspace{.6in}
|
||||
@ -109,40 +108,29 @@
|
||||
\thispagestyle{empty} % eine Leerseite
|
||||
~\vfill
|
||||
|
||||
%\fboxsep 1.36mm
|
||||
%\definecolor{g1}{gray}{0.92}
|
||||
%\newsavebox{\syntaxbox}
|
||||
%\newenvironment{sybox}
|
||||
%{\begin{lrbox}{\syntaxbox}
|
||||
%\begin{minipage}{12.5cm}}
|
||||
%{\end{minipage}
|
||||
%\end{lrbox}
|
||||
%{\fcolorbox{g1}{g1}
|
||||
%{\parbox{12.5cm}{\usebox{\syntaxbox}\hfill\hbox{}}}}}
|
||||
%
|
||||
%\begin{sybox}
|
||||
%Syntaxbox, in der Sonderzeichen wie \verb?%~^? dargestellt werden können.
|
||||
%
|
||||
%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.}
|
||||
%\end{sybox}
|
||||
% Syntax-Boxen (sybox) definieren:
|
||||
TODO: Breite der sybox anpassen
|
||||
\fboxsep 1.36mm
|
||||
\definecolor{g1}{gray}{0.95}
|
||||
\newsavebox{\syntaxbox}
|
||||
\newenvironment{sybox}
|
||||
{\begin{lrbox}{\syntaxbox}
|
||||
\begin{minipage}{\textwidth}}
|
||||
{\end{minipage}
|
||||
\end{lrbox}
|
||||
{\fcolorbox{g1}{g1}
|
||||
{\parbox{\textwidth}{\usebox{\syntaxbox}\hfill\hbox{}}}}}
|
||||
|
||||
|
||||
\footnotesize
|
||||
Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de)\bigskip
|
||||
Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de)
|
||||
|
||||
TODO: Vernünftige Lizenz einsetzen!\bigskip
|
||||
TODO: Vernünftige Lizenz einsetzen!
|
||||
|
||||
%\texttt{${}$Id${}$}\bigskip
|
||||
%\texttt{${}$Id${}$}
|
||||
|
||||
Die aktuellste Version dieses Dokumentes befindet sich auf
|
||||
\href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.\bigskip
|
||||
\href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.
|
||||
|
||||
Dieses Dokument ist entstanden, weil ich für mich selbst eine kompakte
|
||||
Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
|
||||
@ -152,7 +140,7 @@ Hoffnung, da
|
||||
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
|
||||
weitergegeben werden.}
|
||||
|
||||
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und
|
||||
durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in
|
||||
@ -169,7 +157,7 @@ chronologischer Reihenfolge ihres Eingreifens):
|
||||
|
||||
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.\bigskip
|
||||
Rückmeldung.
|
||||
|
||||
Dieses Dokument entstand unter Verwendung von Linux, vim und \LaTeX. Dank an
|
||||
deren Entwickler.
|
||||
@ -184,10 +172,10 @@ deren Entwickler.
|
||||
\pagenumbering{arabic}
|
||||
% Haupttextteil
|
||||
\include{was_ist_die_shell}
|
||||
\include{wo_sind_unterschiede_zu_dos_batchdateien}
|
||||
\include{wofuer_shell_programmierung}
|
||||
\include{wie_sieht_ein_shell_skript_aus}
|
||||
\include{werkzeugkasten}
|
||||
\include{wo_sind_unterschiede_zu_dos_batchdateien}
|
||||
\appendix
|
||||
\include{beispiele}
|
||||
\include{schmutzige_tricks}
|
||||
|
@ -1,30 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,17 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,17 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,24 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{\$ mkdir /usr/local/src/bash/\{old,new,dist,bugs\}}} \\
|
||||
\multicolumn{2}{|X|}{Erzeugt die Verzeichnisse} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/old}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/new}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/dist}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/bugs}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\texttt{\$ chown root /usr/\{ucb/\{ex,edit\},lib/\{ex?.?*,how\b{ }ex\}\}}} \\
|
||||
\multicolumn{2}{|X|}{Weist die folgenden Dateien / Verzeichnisse dem Benutzer root zu:} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/ucb/ex}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/ucb/edit}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/lib/ex?.?*}} \\
|
||||
\multicolumn{2}{|X|}{\textit{/usr/lib/how\b{ }ex}} \\
|
||||
\multicolumn{2}{|X|}{Dabei wird \textit{/usr/lib/ex?.?*} noch weiter expandiert.} \\
|
||||
\end{longtable}
|
@ -1,14 +0,0 @@
|
||||
% $Id$
|
||||
\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 (fast) überall in der Unix-Welt~--~zwischen Groß- und Kleinschreibung unterschieden.} zwischen D und R anfangen
|
||||
\end{longtable}
|
@ -1,19 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,18 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -11,7 +11,7 @@
|
||||
\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 \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist. \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}
|
||||
|
@ -1,12 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{break }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
16
tab_case.tex
16
tab_case.tex
@ -1,16 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,12 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{continue }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
12
tab_exit.tex
12
tab_exit.tex
@ -1,12 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{exit }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
15
tab_for.tex
15
tab_for.tex
@ -1,15 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
18
tab_if.tex
18
tab_if.tex
@ -1,18 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -14,7 +14,7 @@
|
||||
\texttt{|} & Pipe \tabularnewline\STRUT
|
||||
\texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT
|
||||
\texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} für Dateinamen \tabularnewline\STRUT
|
||||
\texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erhält sie durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
|
||||
\texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erhält sie üblicherweise 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 vordefinierten Variable \texttt{\$IFS} abgelegt. Siehe Abschnitt \ref{vordefinierte_variablen}.}
|
||||
|
@ -19,7 +19,7 @@ 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
|
||||
\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.
|
||||
|
@ -1,12 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{return }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
@ -12,6 +12,6 @@ Nummer & Name & Bedeutung \\
|
||||
|
||||
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
|
||||
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}
|
||||
|
@ -1,15 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -1,15 +0,0 @@
|
||||
% $Id$
|
||||
\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}
|
@ -9,12 +9,12 @@ 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
|
||||
also ein eigenes Binary 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++.
|
||||
schreibt man besser in Perl, Python, oder noch besser in einer `compilierten'
|
||||
Sprache wie C oder C++.
|
||||
|
||||
Es stehen jedoch an der Shell viele sehr nützliche externe Kommandos zur
|
||||
Ver\-fü\-gung, die einem die Entwicklung entsprechender eigener Routinen
|
||||
@ -64,7 +64,7 @@ nur Dateien im Sinne von `ein paar Kilobytes Daten, die irgendwo auf der
|
||||
Festplatte rumliegen' gibt. Vielmehr findet man hier die Geräte des Rechners
|
||||
als Dateien unter /dev. Der Kernel selbst stellt Schnittstellen in Form von
|
||||
virtuellen Dateien unter /proc (ab Kernel 2.6 auch unter /sys) zur Verfügung.
|
||||
Und Schlußendlich können Prozesse sich sogenannte Named Pipes\index{Named Pipe}
|
||||
Und schlußendlich können Prozesse sich sogenannte Named Pipes\index{Named Pipe}
|
||||
anlegen, in die sie schreiben oder aus denen sie lesen.
|
||||
|
||||
Diese Kommandos sind also universell nützlich, nicht nur im Zusammenhang mit
|
||||
@ -72,6 +72,7 @@ Dateien auf der Festplatte.
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{cat} (\ref{cat}): Dateien einlesen und ausgeben
|
||||
\item \texttt{date} (\ref{date}): Datum oder Zeit ausgeben
|
||||
\item \texttt{echo} (\ref{echo}): Daten ausgeben
|
||||
\item \texttt{grep} (\ref{grep}): In Dateien suchen
|
||||
\item \texttt{head} (\ref{head}): Dateianfang ausgeben
|
||||
@ -578,6 +579,39 @@ Dateien in Spalten zusammengef
|
||||
\index{cut=\texttt{cut}|)}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{date}\label{date}\index{date=\texttt{date}|(textbf}
|
||||
|
||||
Ein einfacher Aufruf von \texttt{date} führt zu einem Ergebnis in der Art:
|
||||
|
||||
\lstinline|Do Jan 27 00:17:51 CET 2005|
|
||||
|
||||
Wie man sieht, wird das Datum auf dem System entsprechend der lokalen
|
||||
Einstellungen ausgegeben. Auf diesem Rechner ist das deutsch, auf den meisten
|
||||
Rechnern wird Englisch voreingestellt sein.
|
||||
|
||||
Neben dieser umfassenden aber starren Ausgabe ist es möglich, das Datum den
|
||||
eigenen Wünschen entsprechend zu formatieren. Ein paar Beispiele:
|
||||
|
||||
\begin{lstlisting}
|
||||
$ date +"%d.%m.%y, %H:%M"
|
||||
27.01.05, 00:17
|
||||
|
||||
$ date +"Heute ist %A."
|
||||
Heute ist Donnerstag.
|
||||
|
||||
$ date +"%A ist der %u. Tag der Woche."
|
||||
Donnerstag ist der 4. Tag der Woche.
|
||||
\end{lstlisting}
|
||||
|
||||
Die zur Formatierung bereitstehenden Platzhalter stehen in der Man-Page.
|
||||
Eigentlich sollte \texttt{\%s} zur Ausgabe der Unix-Systemzeit
|
||||
\footnote{Sekunden seit dem 01.01.1970, 0:00 Uhr} ein naheliegender Parameter
|
||||
sein, leider steht er nur in der GNU-Version von \texttt{date} zur Verfügung.
|
||||
|
||||
\index{date=\texttt{date}|)}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf}
|
||||
|
||||
@ -638,10 +672,12 @@ ist noch einmal aus. So ist es m
|
||||
Variablen zu bilden.
|
||||
|
||||
Eine wichtige Anwendung für dieses Kommando ist der Fall, wenn eigentlich ein
|
||||
Array\index{Array} gebraucht würde. Der Inhalt eines Array-Elements kann
|
||||
beispielsweise mittels \lstinline|eval echo \$arr$index| ausgegeben
|
||||
werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name
|
||||
der Variablen, die den Index des auszugebenden Elementes enthält.
|
||||
Array\index{Array} gebraucht würde. Wenn \texttt{arr} der Name des Arrays und
|
||||
\texttt{index} der Name der Variablen ist, die den Index des auszugebenden
|
||||
Elementes enthält, dann kann durch die folgende Zeile der Inhalt eines
|
||||
Array-Elementes ausgegeben werden:
|
||||
|
||||
\lstinline|eval echo \$arr$index|
|
||||
|
||||
\index{eval=\texttt{eval}|)}
|
||||
|
||||
@ -820,12 +856,12 @@ ein Skript auf Signale reagieren kann.
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}\marginpar{GNU!}
|
||||
\subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}
|
||||
|
||||
Im Abschnitt über \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein
|
||||
Signal an einen Prozeß schickt, dessen ID bekannt ist. Kennt man die ID nicht,
|
||||
oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando auf
|
||||
GNU-Systemen eine große Hilfe darstellen.
|
||||
vielen Systemen eine große Hilfe darstellen.
|
||||
|
||||
Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es
|
||||
geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale
|
||||
@ -1626,7 +1662,7 @@ sich auch nochmal eine ausf
|
||||
Ein weiterer nützlicher Einsatz für \texttt{trap} ist es, Signale zu
|
||||
ignorieren. Das kann gewünscht sein, wenn eine Folge von Kommandos in einem
|
||||
Skript auf keinen Fall unterbrochen werden darf. Um zu verhindern daß ein
|
||||
\Ovalbox{CTRL}-\Ovalbox{C} des Benutzers das Skript beendet wird folgendes
|
||||
\Ovalbox{CTRL}+\Ovalbox{C} des Benutzers das Skript beendet wird folgendes
|
||||
Konstrukt eingesetzt:
|
||||
|
||||
\begin{lstlisting}
|
||||
@ -1737,14 +1773,18 @@ unterscheidet sich von System zu System}.
|
||||
|
||||
Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist
|
||||
das Vermeiden von Schleifen. Das obige Problem ließe sich auch mit einer Zeile
|
||||
in der Form \lstinline|find / -name \*.txt -exec grep 'text' {} \;| lösen.
|
||||
Allerdings hätte das den Nachteil, daß für jede gefundene Datei ein neuer
|
||||
\texttt{grep} gestartet werden muß. Das kostet Resourcen.
|
||||
in der folgende Form lösen:
|
||||
|
||||
Beide Probleme werden durch eine Zeile in der Form
|
||||
\lstinline+find / -name \*.txt | xargs grep 'text'+ umgangen. Dabei liest
|
||||
\texttt{xargs} aus der Standardeingabe die Parameter, die dann an den
|
||||
\texttt{grep}-Aufruf angehängt werden. Sollten zu viele Dateien gefunden
|
||||
\lstinline|find / -name \*.txt -exec grep 'text' {} \;|
|
||||
|
||||
Allerdings hätte das den Nachteil, daß für jede gefundene Datei ein neuer
|
||||
\texttt{grep} gestartet werden muß. Das kostet Resourcen. Beide Probleme werden
|
||||
durch eine Zeile in der folgenden Form umgangen:
|
||||
|
||||
\lstinline+find / -name \*.txt | xargs grep 'text'+
|
||||
|
||||
Dabei liest \texttt{xargs} aus der Standardeingabe die Parameter, die dann an
|
||||
den \texttt{grep}-Aufruf angehängt werden. Sollten zu viele Dateien gefunden
|
||||
werden, wird \texttt{grep} mehrfach aufgerufen, allerdings im Gegensatz zum
|
||||
obigen Beispiel nicht einmal pro Fundstelle.
|
||||
|
||||
|
@ -82,9 +82,9 @@ einfach durch \lstinline|./skriptname| sondern durch
|
||||
\lstinline|sh -x ./skriptname|.
|
||||
|
||||
\item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der
|
||||
Aufruf über \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede
|
||||
Zeile vor der Ausführung aus, allerdings im Gegensatz zu \texttt{-x} nicht in
|
||||
der expandierten sondern in der vollen Form.
|
||||
Aufruf von der Kommandozeile über \lstinline|sh -v ./skriptname| funktioniert.
|
||||
Diese Option gibt jede Zeile vor der Ausführung aus, allerdings im Gegensatz zu
|
||||
\texttt{-x} nicht in der expandierten sondern in der vollen Form.
|
||||
|
||||
\item \texttt{set -e}: Alle gängigen Shell-Kommandos liefern einen
|
||||
Rückgabewert, der Auskunft über Erfolg oder Mißerfolg gibt (siehe Abschnitt
|
||||
@ -152,13 +152,22 @@ der Variable \texttt{\$?}\index{\$?=\texttt{\$?}} abgelegt.
|
||||
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}
|
||||
\begin{lstlisting}
|
||||
$ cp datei /tmp
|
||||
$ echo $?
|
||||
0
|
||||
|
||||
$ cp datie /tmp
|
||||
cp: datie: Datei oder Verzeichnis nicht gefunden
|
||||
$ echo $?
|
||||
1
|
||||
\end{lstlisting}
|
||||
|
||||
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}
|
||||
\lstinline/$ lpr datei && rm datei/\index{\&\&=\texttt{\&\&}}
|
||||
|
||||
Näheres zur Verknüpfung von Aufrufen steht im Kapitel über Befehlsformen
|
||||
(\ref{befehlsformen}). Beispiele zur Benutzung von Rückgabewerten in Schleifen
|
||||
@ -303,7 +312,22 @@ Die folgenden Zeichen k
|
||||
\LTXtable{\textwidth}{tab_quoting_zeichen.tex}
|
||||
|
||||
\medskip\emph{Beispiele:}\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_beisp_quoting.tex}
|
||||
|
||||
\begin{lstlisting}
|
||||
$ echo 'Ticks "schützen" Anführungszeichen'
|
||||
Ticks "schützen" Anführungszeichen
|
||||
|
||||
$ echo "Ist dies ein \"Sonderfall\"?"
|
||||
Ist dies ein "Sonderfall"?
|
||||
|
||||
$ echo "Sie haben `ls | wc -l` Dateien in `pwd`"
|
||||
Sie haben 43 Dateien in /home/rschaten
|
||||
|
||||
$ echo "Der Wert von \$x ist $x"
|
||||
Der Wert von $x ist 100
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\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|)}
|
||||
|
||||
@ -326,7 +350,18 @@ Die wichtigsten Meta-Zeichen sind:\nopagebreak
|
||||
werden nicht von jeder Shell unterstützt.
|
||||
|
||||
\medskip\emph{Beispiele:}\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_beisp_metazeichen.tex}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Alle Dateien listen, die mit 'neu' anfangen:
|
||||
$ ls neu*
|
||||
|
||||
# 'neuX', 'neu4', aber nicht 'neu10' listen:
|
||||
$ ls neu?
|
||||
|
||||
# Alle Dateien listen, die mit einem Grossbuchstaben zwischen D und R
|
||||
# anfangen - Natuerlich ist die Shell auch hier Case-Sensitive:
|
||||
$ ls [D-R]*
|
||||
\end{lstlisting}
|
||||
|
||||
Hier ist anzumerken, daß Hidden Files (Dateien, deren Name mit einem Punkt
|
||||
beginnt) nicht durch ein einfaches \texttt{*} erfaßt werden, sondern nur durch
|
||||
@ -410,7 +445,22 @@ expandierten Text erhalten. So lassen sich auch Variablen durch diese Technik
|
||||
erzeugen.
|
||||
|
||||
\medskip\emph{Beispiele:}\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_beisp_klammerexpansion.tex}
|
||||
\begin{lstlisting}
|
||||
# Folgende Verzeichnisse erzeugen:
|
||||
# - /usr/local/src/bash/old
|
||||
# - /usr/local/src/bash/new
|
||||
# - /usr/local/src/bash/dist
|
||||
# - /usr/local/src/bash/bugs
|
||||
$ mkdir /usr/local/src/bash/{old,new,dist,bugs}
|
||||
|
||||
# Die folgenden Dateien / Verzeichnisse dem Benutzer root zuweisen:
|
||||
# - /usr/ucb/ex
|
||||
# - /usr/ucb/edit
|
||||
# - /usr/lib/ex?.?*
|
||||
# - /usr/lib/how_ex
|
||||
# Dabei wird /usr/lib/ex?.?* noch weiter expandiert.
|
||||
$ chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
|
||||
\end{lstlisting}
|
||||
\index{Klammer-Expansion|)}
|
||||
|
||||
|
||||
@ -515,7 +565,11 @@ der Bourne-Shell wirkt das f
|
||||
|
||||
\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.
|
||||
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.
|
||||
|
||||
\begin{lstlisting}
|
||||
if who | grep $1 > /dev/null; then # who: Liste der Benutzer
|
||||
@ -561,7 +615,13 @@ Funktion aufgerufenen Kommandos, es sei denn man gibt mittels
|
||||
Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach
|
||||
durch die Eingabe von \texttt{count}.
|
||||
|
||||
\LTXtable{\textwidth}{tab_beisp_funktionen.tex}
|
||||
\begin{lstlisting}
|
||||
count () {
|
||||
ls -1 | wc -l # ls: Liste aller Dateien im Verzeichnis
|
||||
# Mit Parameter -1 einspaltig
|
||||
# wc: Word-Count, zählt mit Parameter -l Zeilen
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\index{Funktion|)}
|
||||
|
||||
@ -604,17 +664,50 @@ Bedingungen k
|
||||
|
||||
\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 \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.
|
||||
\begin{sybox}
|
||||
\texttt{if }\textsl{Bedingung1} \\
|
||||
\texttt{then }\textsl{Befehle1} \\
|
||||
\textsl{[}\texttt{ elif }\textsl{Bedingung2} \\
|
||||
\hspace*{1em}\texttt{then }\textsl{Befehle2 ]} \\
|
||||
\hspace*{1em}\texttt{\vdots} \\
|
||||
\textsl{[}\texttt{ else }\textsl{Befehle3 ]} \\
|
||||
\texttt{fi}
|
||||
\end{sybox}
|
||||
|
||||
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.
|
||||
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}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Fuege eine 0 vor Zahlen kleiner 10 ein:
|
||||
if [ $counter -lt 10 ]; then
|
||||
number=0$counter
|
||||
else
|
||||
number=$counter;
|
||||
fi
|
||||
|
||||
# Loesche ein Verzeichnis, wenn es existiert:
|
||||
if [ -d $dir ]; then
|
||||
rmdir $dir # rmdir: Verzeichnis loeschen
|
||||
fi
|
||||
\end{lstlisting}
|
||||
|
||||
\index{if=\texttt{if}|)}
|
||||
|
||||
|
||||
@ -624,14 +717,54 @@ Bedingungen werden normalerweise mit dem Befehl \texttt{test}\index{test=\texttt
|
||||
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.
|
||||
\begin{sybox}
|
||||
\texttt{case }\textsl{Wert}\texttt{ in} \\
|
||||
\hspace*{1em}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;} \\
|
||||
\hspace*{1em}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;} \\
|
||||
\hspace*{1em}\texttt{\vdots} \\
|
||||
\texttt{esac} \\
|
||||
\end{sybox}
|
||||
|
||||
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.
|
||||
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}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Mit dem ersten Argument in der Befehlszeile wird die entsprechende
|
||||
# Aktion festgelegt:
|
||||
case $1 in # nimmt das erste Argument
|
||||
Ja|Nein) response=1;;
|
||||
-[tT]) table=TRUE;;
|
||||
*) echo "Unbekannte Option"; exit 1;;
|
||||
esac
|
||||
|
||||
# Lies die Zeilen von der Standard-Eingabe, bis eine Zeile mit einem
|
||||
# einzelnen Punkt eingegeben wird:
|
||||
while :; do # Null-Befehl (immer wahr)
|
||||
echo "Zum Beenden . eingeben ==> \c"
|
||||
read line # read: Zeile von StdIn einlesen
|
||||
case "$line" in
|
||||
.) echo "Ausgefuehrt"
|
||||
break;;
|
||||
*) echo "$line";;
|
||||
esac
|
||||
done
|
||||
\end{lstlisting}
|
||||
|
||||
\index{case=\texttt{case}|)}
|
||||
|
||||
|
||||
@ -648,7 +781,13 @@ trotzdem eine Laufvariable\index{Laufvariable} braucht, mu
|
||||
\ref{while}).}.
|
||||
|
||||
Die Syntax der \texttt{for}-Schleife lautet wie folgt:\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_for.tex}
|
||||
|
||||
\begin{sybox}
|
||||
\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]} \\
|
||||
\texttt{do} \\
|
||||
\hspace*{1em}\textsl{Befehle} \\
|
||||
\texttt{done}
|
||||
\end{sybox}
|
||||
|
||||
Die \textsl{Befehle} werden ausgeführt, wobei der Variablen \textsl{x}
|
||||
nacheinander die Werte aus der \textsl{Liste} zugewiesen werden. Wie man sieht
|
||||
@ -661,21 +800,67 @@ 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}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Seitenweises Formatieren der Dateien, die auf der Befehlszeile
|
||||
# angegeben wurden, und speichern des jeweiligen Ergebnisses:
|
||||
for file do
|
||||
pr $file > $file.tmp # pr: Formatiert Textdateien
|
||||
done
|
||||
|
||||
# Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):
|
||||
for item in `cat program_list` # cat: Datei ausgeben
|
||||
do
|
||||
echo "Pruefung der Kapitel auf"
|
||||
echo "Referenzen zum Programm $item ..."
|
||||
grep -c "$item.[co]" chap* # grep: nach Muster suchen
|
||||
done
|
||||
|
||||
# Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn
|
||||
# als neuen Dateinamen:
|
||||
for file do
|
||||
name=`sed -n 's/NAME: //p' $file`
|
||||
# sed: Skriptsprache zur Textformatierung
|
||||
mv $file $name # mv: Datei verschieben bzw. umbenennen
|
||||
done
|
||||
\end{lstlisting}
|
||||
|
||||
\index{for=\texttt{for}|)}
|
||||
|
||||
|
||||
\subsection{while\ldots}\label{while}\index{while=\texttt{while}|(textbf}\index{Schleife>while-=\texttt{while}-|see{while}}
|
||||
|
||||
Die \texttt{while}-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist: die Kopfgesteuerte Schleife.
|
||||
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.
|
||||
\begin{sybox}
|
||||
\texttt{while }\textsl{Bedingung}\texttt{; do} \\
|
||||
\hspace*{1em}\textsl{Befehle} \\
|
||||
\texttt{done}
|
||||
\end{sybox}
|
||||
|
||||
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}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Zeilenweise Ausgabe aller Aufrufparameter:
|
||||
while [ -n "$1" ]; do
|
||||
echo $1
|
||||
shift # mit shift werden die Parameter nach
|
||||
# Links geshiftet (aus $2 wird $1)
|
||||
done
|
||||
\end{lstlisting}
|
||||
|
||||
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}}.
|
||||
@ -688,7 +873,15 @@ das Kommando \texttt{seq} (Siehe Abschnitt \ref{seq}) zur Verf
|
||||
man die Funktion durch geschickte Anwendung der
|
||||
\texttt{while}-Schleife:\nopagebreak
|
||||
|
||||
\LTXtable{\textwidth}{tab_beisp_while_for.tex}
|
||||
\begin{lstlisting}
|
||||
# Ausgabe der Zahlen von 1 bis 100:
|
||||
i=1
|
||||
while [ $i -le 100 ]; do
|
||||
echo $i
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
\end{lstlisting}
|
||||
|
||||
\index{while=\texttt{while}|)}
|
||||
|
||||
|
||||
@ -702,7 +895,12 @@ Es ist also auch eine kopfgesteuerte Schleife, die allerdings so lange l
|
||||
wie die angegebene Bedingung nicht zutrifft.
|
||||
|
||||
Die Syntax der \texttt{until}-Schleife lautet wie folgt:\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_until.tex}
|
||||
|
||||
\begin{sybox}
|
||||
\texttt{until }\textsl{Bedingung}\texttt{; do} \\
|
||||
\hspace*{1em}\textsl{Befehle} \\
|
||||
\texttt{done}
|
||||
\end{sybox}
|
||||
|
||||
Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der
|
||||
\texttt{if}-Anweisung, mit mit dem Befehl
|
||||
@ -712,33 +910,61 @@ Schleife abgebrochen werden soll, m
|
||||
\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}
|
||||
\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
|
||||
|
||||
|
||||
\begin{lstlisting}
|
||||
# Warten, bis sich der Administrator einloggt:
|
||||
until who | grep "root"; do
|
||||
# who: Liste der Benutzer
|
||||
# grep: Suchen nach Muster
|
||||
sleep 2 # sleep: warten
|
||||
done
|
||||
echo "Der Meister ist anwesend"
|
||||
\end{lstlisting}
|
||||
|
||||
\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.
|
||||
\begin{sybox}
|
||||
\texttt{continue }\textsl{[ n ]}
|
||||
\end{sybox}
|
||||
|
||||
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.
|
||||
\begin{sybox}
|
||||
\texttt{break }\textsl{[ n ]}
|
||||
\end{sybox}
|
||||
|
||||
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}
|
||||
|
||||
\begin{sybox}
|
||||
\texttt{exit }\textsl{[ n ]}
|
||||
\end{sybox}
|
||||
|
||||
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}|)}
|
||||
@ -747,7 +973,10 @@ Die \texttt{exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Par
|
||||
\subsection{return}\label{return}\index{return=\texttt{return}|(textbf}
|
||||
|
||||
Die Syntax der \texttt{return}-Anweisung lautet wie folgt:\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_return.tex}
|
||||
|
||||
\begin{sybox}
|
||||
\texttt{return }\textsl{[ n ]}
|
||||
\end{sybox}
|
||||
|
||||
Mittels \texttt{return} kann eine Funktion (siehe \ref{funktionen}) einen
|
||||
bestimmten Wert zurückgeben. Anderenfalls wird der Exit-Code des letzten in der
|
||||
@ -810,11 +1039,26 @@ Zwischen den Dateideskriptoren und einem Umlenkungssymbol darf kein Leerzeichen
|
||||
\LTXtable{\textwidth}{tab_beisp_datenstroeme.tex}
|
||||
|
||||
\medskip\emph{Beispiel eines Here-Dokuments:}\nopagebreak
|
||||
\LTXtable{\textwidth}{tab_beisp_datenstroeme_here-dokument.tex}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Ein Here-Dokument: Nach dem << wird ein sogenannter Delimiter
|
||||
# angegeben. Alle folgenden Zeilen werden an die Standard-Eingabe von
|
||||
# cat übergeben. Der Text wird durch ein erneutes Vorkommen des
|
||||
# Delimiters (einzeln und am Zeilenanfang) beendet.
|
||||
cat << EOF
|
||||
Dieser Text wird zeilenweise ausgegeben,
|
||||
bis ein einzelnes EOF kommt.
|
||||
EOF
|
||||
\end{lstlisting}
|
||||
|
||||
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}
|
||||
|
||||
\begin{lstlisting}
|
||||
cdrdao read-toc --datafile - cd.toc
|
||||
cdparanoia -q -R 1- - | cdrdao write --buffers 64 cd.toc
|
||||
\end{lstlisting}
|
||||
|
||||
\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{Here-Dokument|)textbf}
|
||||
\index{Datenströme|)}
|
||||
|
@ -4,9 +4,9 @@
|
||||
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-Aliasen\index{Aliase} oder Shell-Funktionen.
|
||||
|
||||
Shell-Skripte können viel mehr als Batchdateien.\bigskip
|
||||
Shell-Skripte können viel mehr als Batchdateien.
|
||||
|
||||
Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von
|
||||
Anweisungen, die nacheinander ausgeführt werden. Es stehen zwar auch einige
|
||||
@ -24,8 +24,8 @@ DOS keine M
|
||||
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}).
|
||||
man bei dem Beispiel in Abschnitt \ref{cdrdao}, in dem eine CD kopiert werden
|
||||
soll.
|
||||
|
||||
Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache
|
||||
vergleichen. Es stehen alle Konstrukte zur Verfügung, die eine
|
||||
|
Loading…
Reference in New Issue
Block a user