🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.bugs.sys5
Article #348

Re: Shell Scripts v. Command Options

#348
From: Martin Weitzel
Date: Sun, 03 Feb 1991 13:32
91 lines
3562 bytes
In article <18964@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
[...]
>There are some obvious places where scripts are warranted - such as where
>the execution time of the commands being executed dominates the execution
>time of the shell.  In the case of short lived commands, such as "who |
>wc -l" it may be questionable - the command doesn't run very long in
>either case.  A more ridiculous example might be where "who -q" is
>implemented somewhat faithfully as a shell script.
             ^^^^^^^^^^^^^^^^^^^ (Hmm, as English is not my native language
I'm not quite sure but I suppose this means the following example was
deliberatly choosen not to show good performance - i.e. the poster is
aware of the complicated way the script does its work.)

>if [ $# != 0 ]; then
>	INPUT=$1
>else
>	INPUT=/etc/utmp
>fi
>USERS=`who $INPUT | cut -d' ' -f1`
>LINE=0
>for USER in $USERS; do
>	LENGTH=`expr $USER : '.*'`
>	if [ `expr $LENGTH + $LINE + 1` -gt 80 ]; then
>		LINE=0
>		echo
>	fi
>	LINE=`expr $LINE + $LENGTH + 1`
>	echo $USER '\c'
>done
>echo
>COUNT=`who $INPUT | wc -l | sed -e 's/ *//g'`
>echo '# users='$COUNT

IMHO one problem is - as shown here - that often programming techniques
useful in other languages are simply transliterated into the shell. The
experienced shell programmer will generally try to avoid `expr ...` (and
if he or she allready programmed under V7 also `test ...`), especially
in the body of some often executed loop.

An improvement to the above script avoids two `expr ....` within the
body of the loop and reduces usr-time to 40% and sys-time to 30% of the
original example (timings are taken on my 386-box and I'm aware of the
difficulties timing a shell script containing pipes; as the most complex
part is at the end of the pipe this shouldn't matter too much).

case $# in
0) INPUT=/etc/utmp;;
1) INPUT=$1;;
esac
NL=''
who $INPUT |
pr -tn | (
	while read num usr rest
	do
		if [ `expr "$OUTLINE$usr " : '.*'` -gt 80 ]
		then
			echo "$NL$OUTLINE"'\c'
			NL='\n'
			OUTLINE="$usr "
		else
			OUTLINE="$OUTLINE$usr "
		fi
		count=$num
	done
	echo "$NL$OUTLINE"
	echo "# users=$count"
)

I think the above algorithm is not less obvious than the original example.
The remaining `expr ...` in the body of the loop could also be changed into

	case "$OUTLINE$usr"
	????????<80 question marks total>?????????*)
		echo "$NL$OUTLINE"'\c'
		NL='\n'
		OUTLINE="$usr "
		;;
	*)
		OUTLINE="$OUTLINE$usr "
		;;
	esac

but I'd only choose that if I were hunting for performance, because it
looks a bit obscure. (BTW: This last optmization reduces usr-time to
25% and sys-time to 5% of the original example.)

Conclusion: Most languages have more and less efficient ways to do one
and the same thing. Doing it the way you achieve good performance in
one language may not fit well to some other language and vice versa.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83
Technical Details
Message-ID: <1083@mwtech.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!unido!mikros!mwtech!martin
References: <18899@rpp386.cactus.org> <1991Jan14.202053.20054@zoo.toronto.edu> <18946@rpp386.cactus.org> <1991Jan16.175908.3338@zoo.toronto

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!unido!mikros!mwtech!martin
From: martin@mwtech.UUCP (Martin Weitzel)
Newsgroups: comp.bugs.sys5
Subject: Re: Shell Scripts v. Command Options
Message-ID: <1083@mwtech.UUCP>
Date: 3 Feb 91 13:32:53 GMT
References: <18899@rpp386.cactus.org> <1991Jan14.202053.20054@zoo.toronto.edu> <18946@rpp386.cactus.org> <1991Jan16.175908.3338@zoo.toronto
Reply-To: martin@mwtech.UUCP (Martin Weitzel)
Organization: MIKROS Systemware, Darmstadt/W-Germany
Lines: 91