From 31924e5ab5c59b978c33d68ceaa464d1a08a5027 Mon Sep 17 00:00:00 2001 From: rschaten Date: Mon, 25 Mar 2002 13:48:40 +0000 Subject: [PATCH] Subshell-Schleifen vermeiden --- schmutzige_tricks.tex | 65 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/schmutzige_tricks.tex b/schmutzige_tricks.tex index 0ed40bc..b139f7d 100644 --- a/schmutzige_tricks.tex +++ b/schmutzige_tricks.tex @@ -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.