Fixed calculations in Unix scripts

Although I’ve already shown you how to sum numbers up in bash, I only covered the bash way of doing it. I really like scripting with bash, but when it comes to calculations, there’s quite a few important features missing from bash, and fixed point (thanks for the correction, Azrael Tod!) calculations is one of them. Fortunately, bc command comes as a standard in most Unix distros, and can be used for quite complex calculations.

Basic calculations with bc

bc is a very simple command. It takes standard input as an expression and then evaluates this, performing all the necessary calculations and showing you the result. Thus, to quickly sum numbers up or get a result of some other calculation, simply echo the expression and then pipe it out to the bc command:

ubuntu$ echo "1+2" | bc
3

Now, in scripts your calculations with bc are done quite similarly to what we did in bash. Here’s an example:

ubuntu$ NUMBER1=1
ubuntu$ NUMBER2=2
ubuntu$ SUM=$(echo "$NUMBER1+$NUMBER2"| bc)
ubuntu$ echo $SUM
3

I told you these calculations would be basic, right? Now onto the more interesting stuff!

Fixed point calculations with bc

Most people learn about bash math limitations when they attempt to do a simple calculation but can’t get the current answer with fixed point values. By default, all the operations happen with integers, and that’s what you would get:

ubuntu$ echo "1/2" | bc
0

Now, if you expect 0.5 to be the result of dividing 1 by 2, you need to explain it to bc, because by default it doesn’t show you any fractional part of the number.

The way you do this is quite simple: all you have to do is specify the number of digits you’d like to see  after the radix point of your result. For example, if I set this number to 5, I’ll get bc to output the result of my calculation with 5 digits after the radix point. The special keyword to convey this intention to the bc command is called scale. Just specify the scale value and separate it from the rest of your expression by the semicolon sign:

ubuntu$ echo "scale=5; 1/2" | bc
.50000

Here’s another example:

ubuntu$ echo "scale=5; 0.16*10.79" | bc
1.7264

Hope this answers your question! bc command is very powerful, so I’ll definitely have to revisit it again in the future. For now though, enjoy the fixed point calculations and be sure to ask questions if you think I can help!

See also:




Command Aliases in Unix shells

One of the really useful features almost every Unix shell has is support for command aliases – a way to run a command or a series of Unix commands using a shorter name you get associated with such commands.

An example of a command alias in Unix shell

Here’s one of the most useful aliases I have for Solaris systems:

solaris$ alias ls='/usr/local/gnu/bin/ls --color -F'

What is allows me to do is to simply type “ls” instead of the really long command line it refers to: /usr/local/gnu/bin/ls –color -F.

You see, the ls command which is shipped with Solaris, doesn’t have many options of the more up-to-date GNU ls command, and working with many Linux systems I quite like some of them like color highlighting of different directory objects – files, directories and executables.

Try typing the longer command a few times in a row, and compare it to the “ls” to get the idea of how much of a productivity gain one command alias can be!

Why you should use command aliases

Like many other things in Unix, aliases are a way to become more productive. The general rule of thumb is this: if you have to run some command something more than once every day – consider creating an alias for it. These are just a few cases where it makes sense to employ them:

  • if you repeatedly check whether some files exist or get updated
  • if you’re monitoring a certain aspect of your OS and you get the values using grep command
  • if you’re connecting to the same hosts using rsh or ssh

All of these and many more examples are greatly simplified if you alias them to some shorter commands.

Creating new aliases in bash

Setting up a new alias is quite easy, the syntax for alias command is very straightforward. Let’s say I want to automate the confirmation of swap usage based on a free command in Linux:

redhat$ free
total       used       free     shared    buffers     cached
Mem:       2075156     945712    1129444          0     177292     503416
-/+ buffers/cache:     265004    1810152
Swap:      2040244          0    2040244

The result I’m after is this command:

redhat$ free | grep Swap
Swap:      2040244          0    2040244

And here’s how I can create an alias called “swp” which refers to this series of commands:

redhat$ alias swp='free | grep Swap'

Once you execute this command, you can start using swp as a Unix command:

redhat$ swp
Swap:      2040244          0    2040244

Important: such a creation of new aliases is going to be only active for your current Unix shell and sub-shells you may spawn. To make your alias permanent, you’ll have to update one of your initialization scripts like. For Linux and bash, you should add the same alias command to your .bashrc file.

Removing aliases in Unix

In very much the same way, you can use the unalias command to get rid of a certain alias. The nature of this command is such that you’ll most likely use it when creating and debugging new aliases. It’s unlikely that you’ll need to use it in your initialization scripts.

Following the example above, here’s how to get rid of the swp alias and verify that it’s gone:

redhat$ unalias swp
redhat$ swp
bash: swp: command not found

How to list your current aliases

If you run the alias command without any parameters, you’ll be shown a full list of aliases currently configured for your user account, here’s an example from one of my systems:

l.      ls -d .* --color=tty
ll      ls -l --color=tty
ls      ls --color=tty
vi      vim

That’s it for today! Stay tuned for a follow-up post which will share some of the examples for command aliases in Unix. If you have some – please leave a comment so that I can share it with others!

See also: