Shell scripting: Arithmetic using expr, bc and dc tools

You will definitely need to do some math sometime or the other on the shell. As always ‘expr’ was the most popular thing out there to do complicated mathematical expressions. I was looking at some other options as well when I came across the bc and dc tools. I will explain each one of them in this post.

expr

This is by far the most famous for doing some math on the bash shell. There are two kinds mainly. One on string expressions and then the usual numericals. I would be writing about the later.

expr 40 % 5
0
expr 40 / 5
8
expr 40 / 5 / 8
1
expr 40 / 5 / 8 + 1
2
expr 40 / 5 / 8 + 1 * 10
expr: syntax error

Of course, while doing multiplication you need to use the escaped character ‘\’ backslash. And thus,

expr 40 / 5 / 8 + 1 \* 10
11

The brackets, division, multiplication, addition and subtraction rules also govern here. Now lets look at the others.

bc

This is a language bc that supports arbitrary precision numbers with interactive execution of statements. It starts by processing code from all the files listed on the command line in the order listed. Now a neat way to calculate stuff is:

echo 2*30/3 | bc
20
echo "20 + 5 * 3" | bc
35

Again this follows the basic BODMAS rules.

dc

Stands for desk calculator. Its an interactive calculator on the shell. It supports the basic arithmetic and uses the standard + – / * symbols but entered after the digits. Once you enter the symbol, get the calculated output by passing ‘p’ similar to our ‘=’ symbol on the calculator. And you can keep going.

dc
98
9
*
p
882
10
/
p
88

If I find more useful tools, I’ll update this post. If you have better ideas to implement this, feel free to suggest!

Shell scripting: Arithmetic using expr, bc and dc tools

Shell scripting: awk tutorial

This is one of the best linux line processing utility I have come across. I can do all sort of stuff. Add, replace, find and index stuff. And basically much more. I’ll just get to the examples.

The Basics:

Suppose we have a file like:

echo $somefile
this_is_something_interesting

echo $somefile | awk -F '_' '{print toupper($3)}'
SOMETHING

Now, -F is the field delimiter. And we split the contents of the variable or a file based on the delimiter, which in our case is ‘_’. Now print is the standard function to print out stuff. Now $3 contains the third split value, which in this case is ‘something’. toupper() converts this to uppercase. Duh!.

This example shows how awk converts a string into an array.

echo $time
10:20:30

hms=`echo $time | awk '{split($0,a,":"); print a[1], a[2], a[3]}'`
echo $hms
10 20 30

How the delimiter is ‘:’. Store the splits into variable a which acts like an array. a[2] contains the second split 20 and so on.

Okay, so how do the get the second last or last split of a string?

c=`echo $i | awk 'BEGIN{FS="_"}{for (i=1; i<=NF; i++) if (i==NF-1) print $i}'` # NF contains total number of splits and variable c contains the second last word-split.

This is the basic syntax. You start with BEGIN, where you mention the field seperator FS. Now, NF is a special variable that contains the number of splits. So we loop through the condition, till we reach NF-1, the second last split, which we check using the ‘if’ condition. Then just print it out of course!

Substitution using awk:
This is done using ‘sub’. The first and only the FIRST occurrence of ‘shower’ is replaced by ‘steam’. ‘$0’ means the entire string.

text=`echo $text | awk '{sub("shower","stream"); print $0}'` # substitution only first

Global substitution using awk:
Using ‘gsub’, the entire string or file is replaced. Now, a[a-z] means, all words starting with a and followed by any alphabet, is to be replaced by x.

text1=`echo $text | awk '{gsub("a[a-z]","x"); print $0}'` # global, a followed by an alpha replaced by x

Similarly, the condition here is to replace anything between ‘a’ and ‘d’ with ‘tt’.

text2=`echo $text | awk '{sub("a*d","tt"); print $0}'` # a followed by anything till d, replace d with tt

Similarly for numbers:

cat=`echo $name | awk '{sub("[0-9]+",""); print $0}'` # first occurance removes numbers

Another example:

short=`echo $name | awk '{gsub("[b-z]",""); print $0}'` # global removes all from b to z and replace with ''

Substring using awk:
Suppose we want just the part of the string. (12,8) means go to the 12th character, and get me the next 8 characters.

echo $caption
thisislinuxjunkies

object=`echo $caption | awk '{print substr($0,12,8)}'` # substring
echo $object
inuxjunk

Reading a particular set of lines:
‘NR’ is a special variable with awk which tells us about the number of lines read.

echo $myfile
a
b
c
d
awk 'NR < 3' $myfile # number of lines read in a file
a
b

This is not a complete set of things you get to do with awk. I’ll update this post if I find more neat tricks! Questions appreciated! 🙂

Shell scripting: awk tutorial

Shell scripting: alias tutorial

This is a neat little utility on the bash shell. Aliases allow a string to be substituted for a word when it is used as the first word of a simple command.

#alias#
alias today='date +"%A, %B %-d, %Y"' #Tuesday, October 18, 2011

And how do you undo this alias? Simple.

unalias today

Now typing today on the terminal returns “Tuesday, October 18, 2011”. These are some neat little tricks I think are required on any linux box.

Use alias to fix missing space typos.

alias cd..='cd ..'
alias ..='cd ..'

Display the working directory.

alias .='echo $PWD'

Prevent accidental deletions by making rm interactive.

alias rm='rm -i'

I hope this will get you started! 🙂

Shell scripting: alias tutorial