Skip site navigation (1)Skip section navigation (2)
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>

next in thread | previous in thread | raw e-mail | index | archive | help

--fx1QzQyU29xyWDn1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

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.
=20
>...
> What I usually do in similar shell scripts is something like:
>=20
>     cat "${filename}" | sed -n -e '/foo/ s/bar/baz/' | \
>         xargs -n1 blah
>=20
> This isn't exactly the same as assigning $foo to the results of the
> loop, but you can also use:
>=20
>     foo=3D`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)?
>=20
> 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 =3D 1; k <=3D NF; k++)
>      6                  tag[k] =3D $k;
>      7  }
>      8
>      9  #
>     10  # For all other lines, just print the tagged field values.
>     11  #
>     12  $0 !~ /^Name/ {
>     13          name =3D $1;
>     14          for (k =3D 1; k <=3D NF; k++) {
>     15                  if ($k =3D=3D "-")
>     16                          $k =3D "0";
>     17                  printf "%s_%s: %s\n", tag[k], name, $k;
>     18          }
>     19  }
>=20
> $ 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
--=20
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.

--fx1QzQyU29xyWDn1
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (FreeBSD)

iEYEARECAAYFAkio8FoACgkQmprOCmdXAD3GdQCfUjQnskJmIH4Y0vPZmpDEgowb
Bo8AnA+W7KVKPGH3+rFUurVp+W/zvwHK
=tQNG
-----END PGP SIGNATURE-----

--fx1QzQyU29xyWDn1--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080818034531.GZ44815>