Viele Aenderungen, Tabellen durch Syntax-Boxen ausgetauscht, neues Kapitel: date
This commit is contained in:
@@ -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<EFBFBD>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<64> die M<>use tanzen!"
|
||||
\end{lstlisting}
|
||||
|
||||
Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zur<75>ckmeldet.
|
||||
Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis
|
||||
\texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose
|
||||
Suche) zur<75>ckmeldet.
|
||||
|
||||
|
||||
\section{Subshell-Schleifen vermeiden}\label{subshellschleifen}
|
||||
|
||||
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
|
||||
z<EFBFBD>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 <20>bergibt. Das \texttt{read}-Kommando in der
|
||||
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bi<42>chen Auswertung.
|
||||
|
||||
Es ist zu beobachten, da<64> bei der Ausgabe in Zeile 7 die Variable
|
||||
\texttt{\$count} korrekte Werte enth<74>lt. Um so unverst<73>ndlicher ist es, da<64> sie
|
||||
nach der Vollendung der Schleife wieder den Wert 0 enth<74>lt.
|
||||
|
||||
Das liegt daran, da<64> diese Schleife als Teil einer Pipe in einer Subshell
|
||||
ausgef<EFBFBD>hrt wird. Die Variable \texttt{\$count} steht damit in der Schleife
|
||||
praktisch nur lokal zur Verf<72>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<65>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<7A> gesandt, das ihn
|
||||
bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und
|
||||
tr<EFBFBD>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<75>lliger Reihenfolge abspielt. Damit dieses
|
||||
Problem f<>r uns eine Herausforderung darstellt\footnote{Denn schlie<69>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,
|
||||
<EFBFBD>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<65>nschten Ergebnis. Da die Unterverzeichnisse
|
||||
nicht die Extension `*.pl' tragen, werden sie nicht ber<65>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<65>nschten Ergebnis. Da die
|
||||
Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
|
||||
ber<EFBFBD>cksichtigt. F<>r die Suche in Unterverzeichnissen ziehen wir \texttt{find}
|
||||
(Siehe Abschnitt \ref{find}) heran:
|
||||
|
||||
\lstinline|find . -name \*.pl -exec grep strict {} \;|
|
||||
|
||||
|
||||
Reference in New Issue
Block a user