Subshell-Schleifen vermeiden

This commit is contained in:
rschaten 2002-03-25 13:48:40 +00:00
parent 5c655b4df2
commit 31924e5ab5

View File

@ -46,7 +46,68 @@ TODO!!!
TODO!!!
\subsection{Daten aus einer Subshell hochreichen}
\subsection{Subshell-Schleifen vermeiden}
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:
\footnotesize
\begin{listing}[2]{1}
#!/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{listing}
\normalsize
Was ist passiert?
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
\texttt{cat}-Kommando, 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:
\footnotesize
\begin{listing}[2]{1}
#!/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{listing}
\normalsize
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}
TODO!!!
@ -81,3 +142,5 @@ grep "wichtig" <&3 > "$FILE"
\end{listing}
\normalsize
Allerdings sollte man bei dieser Methode beachten, daß man im Falle eines
Fehlers die Quelldaten verliert, da die Datei ja bereits gelöscht wurde.