[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Recomended tutoial(s) on doing arithmetic in Bash scripts



Another external tool at least as good as bc is wcalc and once that package gets installed just run wcalc at the command prompt and you'll have quite a load of examples show up.

On Sun, 5 Mar 2017, tomas@tuxteam.de wrote:

Date: Sun, 5 Mar 2017 11:25:49
From: tomas@tuxteam.de
To: debian-user@lists.debian.org
Subject: Re: Recomended tutoial(s) on doing arithmetic in Bash scripts
Resent-Date: Sun,  5 Mar 2017 16:26:04 +0000 (UTC)
Resent-From: debian-user@lists.debian.org

-----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: