Mailinglist Archive: opensuse (2430 mails)
| < Previous | Next > |
Re: [opensuse] BASH - brain teaser, can it be done without a pipe?
- From: "Brian K. White" <brian@xxxxxxxxx>
- Date: Sun, 20 Apr 2008 07:46:11 -0400
- Message-id: <020b01c8a2dc$213f71d0$6b00000a@venti>
----- Original Message -----
From: "David C. Rankin" <drankinatty@xxxxxxxxxxxxxxxxxx>
To: "suse" <opensuse@xxxxxxxxxxxx>
Sent: Saturday, April 19, 2008 5:35 AM
Subject: [opensuse] BASH - brain teaser, can it be done without a pipe?
Listmates,
I had to parse a file to find the max cputemp and I wanted to do it from the
command line. There were several thousand lines of .25 sec cputemp data
captured while mprime was running. The file format and the command line I
came
up with are:
input:
04:18 trinity~/linux/scripts> tail cputemp.log
20080419 02:32 65.0 C
20080419 02:32 65.0 C
<snipped>
command line and output:
04:17 trinity~/linux/scripts> tmax=0; while read a b t c; do t=$(echo "$t" |
sed -e 's/\.//'); if (( $t > $tmax )); then tmax="$t"; fi; done <
./cputemp.log
; tmax=$(echo "$tmax" | sed -e 's/\([0-9][0-9]\)\([0-9]\)/\1\.\2/'); echo
"Max
temp is: $tmax"
Max temp is: 69.5
MAXTEMP=0
while read DATE TIME TEMP SCALE ;do
[[ 1${TEMP/./} -gt 1${MAXTEMP/./} ]] && MAXTEMP=$TEMP
done <cputemp.log
echo Max Temp is $MAXTEMP
what the guts do in the middle there:
Say TEMP is 23.4 on some record
${TEMP/./} strips out the "." and gives you "234" so that you can do a true
comparison of all the readings.
23.7 is greater than 23.4, and this way you can test that.
Say TEMP is 08.1 on some record.
When I tried this with mock-up data bash returned an error message on all
records where TEMP hada leading 0.
So one cheapskate way to handle that, since we are simply comparing to see
which of 2 values is greater here, is just prepend a 1 to every value when
comparing, but not actually modify the value itself. so instead of [[ $TEMP -gt
$MAX ]], it's [[ 1$TEMP -gt 1$MAX ]]
Neither of those manipulations actually modifies $TEMP or $MAXTEMP, so after
the test it's a simple MAXTEMP=$TEMP and MAXTEMP will hold the original real
value right from the file, with decimal point i place and no leading 1.
The [[ instead of [ just forces the use of the built-in test instead of /bin/[
(which wouldn't get used anyways in the case of bash and recent ksh and
probably zsh too, but, what the heck, if you have to form habits, and being
human, you do, might as well choose to form ones that work in more cases than
not instead of relying on coincidence. That said, half of this answer would
only work in bash/ksh/zsh and not on many legacy /bin/sh anyways.
This may actually be more efficient done in awk however.
There is an article somewhere, maybe on shelldorado? That talks about exactly
this issue of efficiency of making a shell loop, but not have to spawn a
process like awk, vs awk processing the same data so much more efficiently that
it's actually a win to go ahead and spawn the process, because the shell will
actually read the lines of shell in the loop and interpret them over and over
again, where awk only has to interpret the awk commands just once, and process
the data thereafter far more efficiently.
Since a 2 thousand line mockup took a fraction of a second to run on a kind of
an old box, I think it's academic here.
mybox:~ # n=1 >tt ;until [[ $n -gt 2000 ]];do echo 20080419 $n
$(($RANDOM/327)).$(($RANDOM/3277)) C >>tt ;((n++)) ;done
mybox:~ # time eval '(MAXTEMP=0 ;while read DATE TIME TEMP SCALE ;do [[
1${TEMP/./} -gt 1${MAXTEMP/./} ]] && MAXTEMP=$TEMP ;done <tt ;echo Max Temp is
$MAXTEMP)'
Max Temp is 100.9
real 0m0.059s
user 0m0.052s
sys 0m0.008s
mybox:~ #
--
Brian K. White brian@xxxxxxxxx http://www.myspace.com/KEYofR
+++++[>+++[>+++++>+++++++<<-]<-]>>+.>.+++++.+++++++.-.[>+<---]>++.
filePro BBx Linux SCO FreeBSD #callahans Satriani Filk!
--
To unsubscribe, e-mail: opensuse+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse+help@xxxxxxxxxxxx
| < Previous | Next > |