Re: Recomended tutoial(s) on doing arithmetic in Bash scripts
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Sun, Mar 05, 2017 at 09:42:16AM -0600, Richard Owlett wrote:
> I'm interested in "expr" and "bc".
> The man pages lack reasonable examples.
> The tutorial/HOWTO pages confuse the issue with fancy page layouts
> and/or code samples showing how impressive the author can make the
> script's output.
Hm. Neither expr nor bc are bash, they are "external" binaries. If you
want to do arithmetic in bash, there's $((...)):
tomas@rasputin:~$ echo $(( (3+4)/3 ))
2
As you see, this does integer arithmetic. There's not much to it, the
usuall stuff (more or less known from C, like pre/post increment, negation,
bitwise and/or/xor... see the section "ARITHMETIC EVALUATION" in the
bash manual.
Expr and bc can do more -- but you've to take into account that they
are external programs and thus give their response on stdout: you
have to "catch" it somehow to make use of it. The `...` or the more
modern and highly recommended $(...) come in:
tomas@rasputin:~$ foo=$(expr 3 + 4)
tomas@rasputin:~$ echo $foo
7
Note that expr can also only do integers. I don't know whether expr
brings anything to the table beyond portability. If you stick to bash
(or dash, or...) it seems better to keep to the builtin $((...))
If you need floating point numbers, bc (or dc) are your next stops.
Perhaps you start with a couple of small examples on what you want
to achieve, post them here and we take them as riddles :-)
Here's a little example with dc, to get your appetite going. As you
might know, I'm a Luddite and have no desktop environment. As a laptop
user, I'm still interested on my battery's status: my laptop just
quits pretty abruptly when empty, putting the excellent ext4 file
system to test. For that, I've a small xterm which displays the
battery fill status (which I want as a fraction of 1, to five
significant digits, so I can see it's moving). The repeating is
done outside the program, with "watch" -- invoked from my WM.
Here's the shell snippet. The dc magic (dividing the battery's
current status, called NOW, by the FULL status) is done at
the last line:
#!/bin/bash
# Notes:
# for colors:
# tput setaf 1 ; tput bold ; echo -n 123 ; tput setaf 7 ; tput sgr0 ; echo 456
# cf tput(1) terminfo(5)
# do continuous mode with watch -c, possibly t
BAT='/sys/class/power_supply/BAT0'
AC='/sys/class/power_supply/ADP1'
FULL=$(cat $BAT/energy_full)
NOW=$(cat $BAT/energy_now)
case $(cat $AC/online) in
0) online="BAT" ;;
1) online="AC " ;;
*) online="???" ;;
esac
echo -ne "$online " ; dc -e "5k $NOW $FULL / p"
The $online variable tells me whether I'm on AC or BATtery, for the dc line it's
"5k" to set the five significant digits, then $NOW $FULL and the division "/"
(note that dc is a stack calculator [1]), note that the expansion of $NOW, etc.
is done by the shell.
If you wanted to catch the value instead of printing it right away, you would
do $fill=$(dc -e "5k $NOW $FULL / p")
With bc it'd be similar; I never wrapped my head around bc's syntax, since
dc has served me so well, but given enough motivation I don't think it's
too hard.
The script's comments hint at the next steps: COLORZ ;-)
Enjoy
[1] Like "Foot in yourself shoot.": look under Forth here:
http://www.thealmightyguru.com/Humor/Docs/ShootYourselfInTheFoot.html
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
iEYEARECAAYFAli8PA0ACgkQBcgs9XrR2kYGPACfab6u+HPGQbzcvEnfoCAbwjjK
46cAnR9AlDZzX0GrEAtSHwRcmL+syaKE
=LElz
-----END PGP SIGNATURE-----
Reply to: