Shell scripts: variable assignment within read loops

David Wolfskill david at catwhisker.org
Mon Aug 18 03:45:37 UTC 2008


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 at 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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-questions/attachments/20080818/8b56f8b8/attachment.pgp


More information about the freebsd-questions mailing list