[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 The problem was that I had to strip the "." from the temp reading to do the integer comparison in BASH and then I had to add it back to the output to get the decimal place back into the variable. (I know I don't need the decimal to know what the max temp was, but I wanted it there and I though I could learn something in the process) With all the efficiency discussion on the list about reducing pipes, I though I would pose this cl and ask if there is a way to have sed parse the variables $t and $tmax without the echo and | I used above. I tried several things, but none worked (i.e. sed -e 's/\.//' < echo "$t"). Also, if there is a simpler way to do what I did, by all means let me know. What say the gurus? Can it be done? I'm just trying to take the good advise and learn. Thanks -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Saturday 19 April 2008 11:35:49 David C. Rankin wrote:
The problem was that I had to strip the "." from the temp reading to do the integer comparison in BASH and then I had to add it back to the output to get the decimal place back into the variable. (I know I don't need the decimal to know what the max temp was, but I wanted it there and I though I could learn something in the process)
One solution would be to do it in another language, like perl or python, that can do floating point But in bash, something like this might work tmax=0; while read a b c d; do tmpnum=${c/\./}; if [ $tmpnum -gt $tmax ]; then tmax=$tmpnum; fi; done < temps; tmax="${tmax:0:$((${#tmax}-1))}. ${tmax: -1:1}"; echo "Max temp is $tmax" It assumes of course that there is only one decimal, and that it is always there.
With all the efficiency discussion on the list about reducing pipes, I though I would pose this cl and ask if there is a way to have sed parse the variables $t and $tmax without the echo and | I used above. I tried several things, but none worked (i.e. sed -e 's/\.//' < echo "$t"). Also, if there is a simpler way to do what I did, by all means let me know.
sed is almost never needed for things like this. bash can do it internally in almost all cases Anders -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Sat, 19 Apr 2008, David C. Rankin wrote:-
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"
Well, I've unravelled it a bit tmax=0 while read a a t a # no need to use different names for dummy variables do t=${t//\./} # does a global character replace, just like adding 'g' to the end of a 'sed' expression. [ "${t}" -gt "${tmax}" ] && tmax="${t}" # no need for an if ... fi for this done < ./cputemp.log echo "Max temp is: ${tmax::$[${#tmax}-1]}.${tmax:$[${#tmax}-1]}" And since you're in the mood for tips, here's a few more: You can replace basename with ${variable##*/} The ## means to strip off from the beginning of $variable the longest part that matches the string after the ##. In this case, that's a wildcard and a '/' so matches all characters upto the last '/'. You can replace dirname with ${variable%/*} The % means to strip off from the end of $variable the shortest part that matches the string after '%'. In this case, that's a '/' and a wildcard and so matches from the last 'l' to the end of the string. You can use ${variable//[[:digit:]]/} to check if what's supposed to be a number really is: if [ -n "${variable//[[:digit:]]/}" ] then echo "There's non-numeric characters in ${variable}" fi If you're doing some processing of files found using find, as I do when transcoding flash videos to AVIs, you can use something like: find -type f -name "*.flv" | \ while read inpname do outname="${inpname%.flv}.avi" # strip off the .flv extender and add .avi outname="${dest_dir}/${outname##*/}" # now add the destination path and strip off the source path ffmpeg -i "${inpname}" ${ffmpeg_options} "${outname}" && \ mv "${inpname}"{,old} # if the conversion worked, rename the source file so it doesn't get done again done Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
----- Original Message -----
From: "David C. Rankin"
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
----- Original Message -----
From: "Brian K. White"
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
Hello, On Sat, 19 Apr 2008, David C. Rankin wrote:
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
Easy: awk and perl were created for this kind of stuff. awk '$3 > tmax { tmax = $3; } END { printf "Maximum temperature was: %.1f °C\n", tmax; }' cputemp.log More elaborate with the following input: ==== 20080419 02:32 63.3 C 20080419 02:34 64.1 C 20080419 02:36 63.9 C 20080419 02:39 65.3 C 20080419 02:42 64.2 C 20080419 02:49 65.32 C 20080419 02:53 65.3 C 20080419 03:02 64.2 C ==== $ awk ' $3 > tmax { tmax = $3; tdate = $1; ttime = $2; } END { printf "Maximum temperature was: %.1f °C on %s %s\n", tmax, tdate, ttime; }' cputemp.log Maximum temperature was: 65.3 °C on 20080419 02:49 HTH, -dnh --
Mine had one where I think 4 machines were so intertwined that none would boot unless 2 of the others were up. And nothing else would boot till those were up. You are trapped in a maze of twisty little NFS-maps, all different. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
David Haller wrote:
Hello,
Easy: awk and perl were created for this kind of stuff.
awk '$3 > tmax { tmax = $3; } END { printf "Maximum temperature was: %.1f °C\n", tmax; }' cputemp.log
More elaborate with the following input:
==== 20080419 02:32 63.3 C 20080419 02:34 64.1 C 20080419 02:36 63.9 C 20080419 02:39 65.3 C 20080419 02:42 64.2 C 20080419 02:49 65.32 C 20080419 02:53 65.3 C 20080419 03:02 64.2 C ====
$ awk ' $3 > tmax { tmax = $3; tdate = $1; ttime = $2; } END { printf "Maximum temperature was: %.1f °C on %s %s\n", tmax, tdate, ttime; }' cputemp.log Maximum temperature was: 65.3 °C on 20080419 02:49
HTH, -dnh
Thanks Anders, David, Brian and David! I don't now where you guys get this stuff, but it is great. I have learned 4 new ways to skin this cat. Thanks again. One of the days I'll snatch a pebble or two. -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Saturday 2008-04-19 11:35, David C. Rankin wrote:
command line and output:
tmax=0; while read a b t c; do t=$(echo "$t" | sed -e 's/\.//');
sed -e 's/\.//' <<< "$t" oh wait that still involves a pipe... so try these (and enhance your Perl horizons): perl -e '$_=pop;s/\.//;print' "$t" perl -e '$_=pop;y/.//d;print' "$t" perl -e 'print 10*pop' "$t"
if (( $t > $tmax )); then
if [[ "$t" -gt "$tmax" ]]; then
tmax="$t"; fi; done < ./cputemp.log; tmax=$(echo "$tmax" | sed -e 's/\([0-9][0-9]\)\([0-9]\)/\1\.\2/');
perl -le 'split//,pop;print"$_[0]$_[1].$_[2]"' "$tmax" perl -le 'print join".",split/(?<=..)/,pop' "$tmax" perl -le 'print join".",split/(?=.$)/,pop' "$tmax" perl -le 'printf"%u%u.%u",split//,pop' "$tmax" happy perlgolfing.
echo "Max temp is: $tmax"
What say the gurus? Can it be done? I'm just trying to take the good advise and learn.
Guru says implement the whole thing in something non-sh. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
sed -e 's/\.//' <<< "$t"
What is <<< ? I know < and <<, but the above does not look like a typo. Greg -- Greg Freemyer Litigation Triage Solutions Specialist http://www.linkedin.com/in/gregfreemyer First 99 Days Litigation White Paper - http://www.norcrossgroup.com/forms/whitepapers/99%20Days%20whitepaper.pdf The Norcross Group The Intersection of Evidence & Technology http://www.norcrossgroup.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Wednesday 2008-04-23 21:50, Greg Freemyer wrote:
sed -e 's/\.//' <<< "$t"
What is <<< ?
I know < and <<, but the above does not look like a typo.
It really is a triple <. Try it out. (Moral for life: don't ever think you know everything :D) -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Wednesday 23 April 2008 12:50, Greg Freemyer wrote:
sed -e 's/\.//' <<< "$t"
What is <<< ?
I know < and <<, but the above does not look like a typo.
Greg
Type these characters at a shell prompt (omitting the surrounding quotes):
"man bash<ENTER>/<<<<ENTER>"
Oh, my that's a bit ambiguous. After the slash, type three less-than's
and hit ENTER.
Here's what you'll see:
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
Here Strings
A variant of here documents, the format is:
<<
participants (8)
-
Anders Johansson
-
Brian K. White
-
David Bolt
-
David C. Rankin
-
David Haller
-
Greg Freemyer
-
Jan Engelhardt
-
Randall R Schulz