Date: Sun, 17 Aug 2008 20:45:31 -0700 From: David Wolfskill <david@catwhisker.org> To: Giorgos Keramidas <keramida@ceid.upatras.gr> Cc: freebsd-questions@freebsd.org Subject: Re: Shell scripts: variable assignment within read loops Message-ID: <20080818034531.GZ44815@bunrab.catwhisker.org> In-Reply-To: <87ljyvypa8.fsf@kobe.laptop> References: <20080818013328.GY44815@bunrab.catwhisker.org> <87ljyvypa8.fsf@kobe.laptop>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
On Mon, Aug 18, 2008 at 06:29:03AM +0300, Giorgos Keramidas wrote:
> ...
> You are right that feeding data to a looping construct through a pipe
> may run in a subshell. The ``Single UNIX Specification'' says
> ....
Ah; thanks for the confirmation.
>...
> What I usually do in similar shell scripts is something like:
>
> cat "${filename}" | sed -n -e '/foo/ s/bar/baz/' | \
> xargs -n1 blah
>
> This isn't exactly the same as assigning $foo to the results of the
> loop, but you can also use:
>
> foo=`cat $filename | while read bar ; do \
> stuff ...
> echo "$bar"
> more stuff...
> done`
Right; I had seen that type of construct in /etc/rc.d.* (which is where
I often look for samples of shell scripts that need to work reliably).
As you noticed, that won't quite do for what I'm trying to accomplish here.
> ...
> > As you see, I am circumventing the issue by writing to a transient
> > file. In the intended application, the script is to be used to gather
> > resource-utilization information; thus, I want its "footprint" to be
> > smaller, rather than larger. Granted, in my case, I would be writing
> > a tiny text file to a swap-backed tmpfs, but in production, I won't
> > have the luxury of knowing that in advance: the intent is that the
> > script must run on a minimal FreeBSD system, with no "ports" or other
> > 3rd-party software installed.
> >
> > Is there some other -- possibly better -- way to do this (using Bourne
> > shell scripting)?
>
> Ah, that's much better. Now I see what you are trying to do.
:-)
> Would you be ok with an awk(1) script instead of /bin/sh? It tends
> to be nicer for this sort of thing, i.e.:
Yes, awk(1) would be OK. I'll be more inclined to use it if I can
figure out a way to use it instead of sed(1) for a very different part
of the script. :-}
> $ expand david.awk | cat -n
> 1 #
> 2 # Gather the field names if this is a header-line.
> 3 #
> 4 $0 ~ /^Name/ {
> 5 for (k = 1; k <= NF; k++)
> 6 tag[k] = $k;
> 7 }
> 8
> 9 #
> 10 # For all other lines, just print the tagged field values.
> 11 #
> 12 $0 !~ /^Name/ {
> 13 name = $1;
> 14 for (k = 1; k <= NF; k++) {
> 15 if ($k == "-")
> 16 $k = "0";
> 17 printf "%s_%s: %s\n", tag[k], name, $k;
> 18 }
> 19 }
>
> $ netstat -nibd -f inet | awk -f david.awk
> Name_re0: re0
> Mtu_re0: 1500
> Network_re0: 192.168.1.0/2
> ...
Very cool; thank you very much! I will study that a bit....
(I'd normally do this stuff in Perl, but in addition to the other issues
mentioned earlier, the script will be sleeping most of the time, but
wake up & spit out results periodically. The usual case will be every 5
minutes, but I plan to make use of it with radically shorter periods in
certain specialized environments -- such as every 5 seconds. And I
still want it to be low overhead. I also note in passing that in its
"production" environments, the script's standard output will be
redirected to append to a file on a different machine via an SSH tunnel.)
> With a bit of preprocessing, it may be possible to extract the network
> names and print the "(end) NICs: XXX XXX" part too.
Right -- much of the output I demonstrated was strictly for debugging/
expository purposes.
Thanks again, Giorgos!
Peace,
david
--
David H. Wolfskill david@catwhisker.org
Depriving a girl or boy of an opportunity for education is evil.
See http://www.catwhisker.org/~david/publickey.gpg for my public key.
[-- Attachment #2 --]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (FreeBSD)
iEYEARECAAYFAkio8FoACgkQmprOCmdXAD3GdQCfUjQnskJmIH4Y0vPZmpDEgowb
Bo8AnA+W7KVKPGH3+rFUurVp+W/zvwHK
=tQNG
-----END PGP SIGNATURE-----
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080818034531.GZ44815>
