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 [EMAIL PROTECTED] Depriving a girl or boy of an opportunity for education is evil. See http://www.catwhisker.org/~david/publickey.gpg for my public key.
pgpQZk6NuCeRc.pgp
Description: PGP signature