I was surfing the web today here and there when suddenly I stumbled upon a page in The Geek Stuff which explained a shell command called awk. It’s a great tool to search through a text file for a pattern. The site contained many easy to understand examples on the usage of awk.
The basic syntax is:

awk '/search pattern 1/ {actions1}
   /search pattern 2/ {actions2}' filename

Here, actions1 is activated when the search pattern 1 is found and actions2 when search pattern 2 is found. The data is taken from filename.
This command can be manipulated in various ways to achieve many complex tasks in easily. The thought that instantly came to my mind was the Who will win the election script I wrote in the previous blog post. In that, the scripts creates a file named results which will store the results of the poll. An example of a results file is as follows:

MR tham
MR sand
SF hugo
MR bosh
SF dialz

Here, three people (tham, sand and bosh) think that MR will win the election and the other two think that SF will win. Okay, that script we wrote the last time creates this file, but how can we get a summary of the results after the poll? We want to know how many voted for MR and SF respectively.
AWK comes to the rescue. Here’s a script to count the number of votes for MR and SF and display them:

#!/bin/bash
#: Description: Gives a summary of the results of Who Will Win
     the Election?

awk 'BEGIN { mr=0;sf=0; }
$1 ~ /MR/ { mr++; }
/SF/ { sf++; }
END {print "MR =",mr,"\nSF =",sf;}' results

It’s just one command! The output for the results file given above will be as follows:

MR = 3
SF = 2

Seems awk is a great tool to manipulate text files. For more info on awk visit this page.
So bye for now! See ya next time with another script!


Okay, it’s the election time here in Sri Lanka. The presidential election will be held on 26th January 2010. As the heat continue to build, I thought of writing a small script to get to know who will win the election as people think. To make it more user friendly, had to add some GUI features. Hadn’t known how to use these message boxes, etc before, but a simple search in google provided the answers. Here’s the script:

#!/bin/bash

name=$(zenity --entry --text "Please enter your name" 
   --entry-text "" --title "Presidential Election 2010")
if [ $? != 0 ]
then
exit 0
fi

vote=$(gdialog --title "Presidential Election 2010" --radiolist 
   "Who will win?" 60 100 10 1 Mahinda Rajapaksha 2 Sarath 
   Fonseka 2>&1)

if [ $vote = "1" ]; then
result="MR"
fi
if [ $vote = "2" ]; then
result="SF"
fi

result="$result $name"
echo $result >> results

The script will first prompt the user to enter his name. If he didn’t press Cancel in that name entry box, it will show the user a box with two radio buttons with the names of the two candidates, Mahinda Rajapaksha and Sarath Fonseka. Once the user selects an answer and presses Ok that vote will be appended to a text file results along with his name.
The Zenity thing in the script is way to display dialog boxes and such GUI accessories in the shell scripts. Hope to add more of this later.

As far as the votes in our boarding place are concerned, more than 90% percent think Mahinda will win the election. Let’s place that choice in the voters’ hands. 🙂


The editor I use for bash scripting is the VI editor. In fact it is VIM, or Vi IMproved. The other options include gedit, nano and emacs. Any text editor will do the job.

VIM screenshot

You can invoke VI by typing vi in the shell.

   vi

or you can use it followed by the name of the file you’re going to edit.

   vi hello

VI’s steep learning curve usually deters many new comers. You have to remember various key commands to perform even simple tasks. However, once you get in touch with the basics, it’s quite easy to catch up and you will soon find how efficient working with VI is.
VIM is an improved version of VI which is far more intuitive than the former, for example you can use arrow keys to move around the text. It doesn’t make sense to work with VI when VIM is available. Once you install VIM (sudo apt-get install vim in debian-based distros), just invoking vi instead of vim will take you to VIM.

Two good tutorials for learning VI can be found here and here.


Remember the bash script I wrote in the previous post? Well, the script below does the exactly opposite.

#!/bin/bash
#: Description : Reads from a file whose entries are of the 
 format "name1 name2, age" and writes them in a file line 
 by line
#: Author : Thameera
#: Date : 26/12/2009

while IFS= read -r line
do
 (( ${#line}==0 )) && exit 0
 nm="${line%,*}"
 printf "%s\n%s\n%s\n" "${nm% *}" "${nm#* }" "${line:${#nm}+2}"
done

This script widely uses parameter expansion and patterns. For example ${line%,*} removes the shortest match for a comma from the end. The percentage sign here means “remove the shortest match from the end”. The hash (#) sign used in the next line does the same thing the other way around, i.e. “remove the shortest match from the beginning”. The “shortest match” means the first match you find when you go from the end or the beginning. If you double the % or #, it will return the longest match.

For example,

$ var="anaconda"
$ echo ${var##*n}
da

And the ${#nm} expands to the length of the string nm.

When the following input is fed to the script:

chitral gamage, 32
tham sen, 30

the output is given as follows:

chitral
gamage
32
tham
sen
30

So that’s it. It’s just another small script, but helped me a lot to understand how parameter expansion works. See you next time with another script where the bash comes in action!


This is a script I wrote to get in touch with some bash basics.

#!/bin/bash
#: Description	: Reads a file with entries in separated
lines and write them to a file with a comma separated format
#:	Author	: Thameera
#: Date	: 23/12/2009

while IFS= read -r name1
do
	read -r	name2
	read -r age
	if [ -z "$age" ]
	then
		break
	fi
	printf "%s %s, %s\n" "$name1" "$name2" "$age"
done

What this code does is to read from a file specified in the argument list a list with the following format:

firstname1
lastname1
age1
firstname2
lastname2
age2
....

and arrange them in the following order in a new file specified by the argument:

firstname1 lastname1, age1
firstname2 lastname2, age2

Suppose you save this file with the name main and your input is in the file in. Then the command to execute the script should be:

bash main <in >out

This will write the output in a new file called out.

When I first wrote this script, I found out that the output would produce an extra blank line with a comma. The if condition if [ -z “$age” ] was added to rectify this. This condition will break the loop when it finds that the variable age is no longer assigned to a valid value.

Well, it does not do any interesting stuff, but helped me to get touch with some basics. Hope to post some more interesting stuff in the time to come.


Hello

22Dec09

Hello there!

This is Thameera, a student from Sri Lanka. I had this strange interest in learning shell scripting and have just begun learning it. In this blog, I’ll post the various bash scripts I write in the time to come, hopefully with explanations.

Keep in touch!