Wednesday, May 28, 2008

Simple Arithmetic In Bash, Perl and Awk - More Porting

Greetings,

Today we're going to continue along on our series of posts dealing with porting code between the bash shell, Perl and awk. In previous posts, we've looked at the basics regarding simple string variables, simple one-dimensional arrays and associative arrays (sometimes referred to as hashes or "lookup tables.").

Before we move on to logical programming constructs (such as if-conditionals and while-loops), it's important to go over a few other basic concepts that require translation in order to work in the same manner in all three languages. Today we're going to demonstrate how each of bash, Perl and awk deal with simple arithmetic. Note that we won't be dealing specifically with floating point math (although it is possible to do) since that's slightly beyond the scope of this article (but it will be -- huge hint -- the subject of our next post in this series... variable scope, that is ;)

For our purposes today, we're going to assume that we need to solve five different arithmetic equations in each of our three languages. And, coincidentally enough, all five equations need to serve a distinctly different arithmetic purpose. We're going to have to take two integers and perform addition, subtraction, multiplication and division on them, and also extract the remainder of any imperfect divisions (defined herein as any division which doesn't have a remainder of 0). Note that, for all of our "bash" examples, the spaces (or lack thereof) in the equations are "required." Perl and awk will produce results with or without spaces between the operands.

1. Bash: In the bash shell, all of these actions are very simple to perform, and you have a more than a few options at your disposal depending on how you prefer to do them. The one way you can perform shell arithmetic that will work in older versions of the bash shell (or most any other shell) is to use the "expr" commmand. While this is, technically, an entirely separate program, it can come in handy if you get ahold of an older shell that can't perform arithmetic on its own. The syntax for our equations would be the following (We'll be assuming that the side explanations will be the same for Perl and awk to save on space):

host # expr 9 + 2
11
host # expr 9 - 2
7
host # expr 9 \* 2
18
host # expr 9 / 2
<--- Here you can see a limitation of simple integer math in the shell. 9 divided by 2 should be 4.5, but the shell doesn't understand the fraction.
4
host # expr 9 % 2
<--- And here's the reason we want to see the remainder of that division. This shows us that 1 integer was lost in the imperfect division.
1

The bash shell, however, will allow you to do simple arithmetic in a much more simplistic way. And this is it (we'll use the shell built-in "echo" to print the output to the screen):

host # echo $((9+2))
11
host # echo $((9-2))
7
host # echo $((9*2))
18
host # echo $((9/2))
4
host # echo $((9%2))
1


2. Perl: Perl, as we've mentioned in previous posts, provides easy access to the shell via the backtick operators and "system" function, but there's almost no need to ever use those, since Perl can do simple arithmetic on its own. In fact, depending upon how heavily you use a "system" resource from within a Perl program, the slower and more cumbersome that program will become. Using Perl's built-in functions and methods is almost always more efficient.

Here's an example of how we'd do the same arithmetic with Perl, using the command line execution statement (-e flag) method (again, we'll use a print function to spit the output to the terminal):

host # perl -e 'print 9 + 2 . "\n";'
11
host # perl -e 'print 9 - 2 . "\n";'
7
host # perl -e 'print 9 * 2 . "\n";'
18
host # perl -e 'print 9 / 2 . "\n";'
<--- Note, here, how Perl naturally deals with fractions!
4.5
host # perl -e 'print 9 % 2 . "\n";'
1


3. Awk: Awk makes performing arithmetic operations incredibly easy, as well. It, like Perl, also understands simple fractions and accounts for simple floating point arithmetic right out-of-the-box:

host # echo |awk '{print 9+2}'
11
host # echo |awk '{print 9-2}'
7
host # echo |awk '{print 9*2}'
18
host # echo |awk '{print 9/2}'
4.5
host # echo |awk '{print 9%2}'
1


And, that's all there is to it. As you can see, the difference between performing simple arithmetic in all three languages isn't that great. As we continue to examine porting code between these languages, you'll notice a lot of similarities (and a few minor differences ;) which will make the translation of one language to another very simple for you with a little practice and patience.

Our next porting post will deal with variable scope, which we'll both define and demonstrate .

Until then!

, Mike