Unit 4 Notes
Unit 4 Notes
Module - 4
The script runs three echo commands and shows the use of variable evaluation and command
substitution. It also prints the calender of the current month.
script.sh
#!/bin/sh
The comment character (#) can be placed anywhere in a line. The shell ignores all the characters
placed on its right. The first line is interpreter line which begins with #! and is followed by the
pathname of the shell to be used for running the script. This line specifies the Bourne shell. To
run the script, make it executable first and then invoke the script name.
$ chmod +x script.sh
$ script.sh
January 2003
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
My shell: /bin/sh
Shell scripts are executed by a child shell. The child shell reads and executes each statement (in
interpretive mode).
User can explicitly spawn a child of his choice with the script name as argument:
The read statement in the shell’s internal tool for taking input from user i.e making scripts
interactive. It is used with one or more variables. Input supplied through the standard input is
read into these variables. When user use a statement like
read name
The script pauses at that point to take input from keyboard. Whatever user entered is stored in the
variable name. Since this is a form of assignment, no $ is used before name. The script emp1.sh
uses read to take a search string and filename from the terminal. Shell scripts accept comments
prefixed by # anywhere in a line.
#!/bin/sh
read pname
read filename
$ emp1.sh
The script first asks for a pattern to be entered. Input the string director, which is assigned to the
variable pname. The script asks for the filename, enter the string emp.lst ,which is assigned to
the variable flname. grep then runs with these two variables as arguments.
A single read statement can be used with one or more variables to let you enter multiple
arguments.
If the number of arguments supplied is less than the number of variables accepting them, any
leftover variables will simply remain unassigned. When the number of arguments exceeds the
number of variables, the remaining words are assigned to the last variable.
$# - It is set to the number of arguments specified. This lets user to design scripts that check
whether the right number of arguments have been entered.
$0 – Holds the command name itself. You can link a shell script to be invoked by more than one
name. The script logic can check $0 to behave differently depending on the name by which it is
invoked.
#!/bin/sh
# emp2.sh
echo “Program: $0
grep “$1” $2
emp2.sh
The script emp2.sh runs grep with two positional parameters that are set by the script arguments
director and emp.lst
Program: emp2.sh
Job Over
When arguments are specified in this way, the first word(the command itself) is assigned to $0.
The second word (the first argument) to $1. The third word (the second argument) to $2. User
can use positional parameters up to $9. When user use a multiword string to represent a single
command line argument, he must quote it. To look for chanchal singhvi, use emp2.sh “chanchal
singhvi “ emp.lst All assignments to positional and special parameters are made by the shell.
There are two very common exit values. User don’t need to place exit statement at the end of
every shell script because the shell understands when script execution is complete. It’s through
the exit command or function that every command returns an exit status to the caller. A
command is said to return a true exit status if it executes successfully and false if it fails.
$ cat foo
The shell offers a variable ($?) and a command (test) that evaluates a command’s exit status.
The Parameter $?
The paameter $? stores the exit status of the last command. It has the value 0 if the command
succeds and a nonzero value if it fails. This parameter is set by exit’s argument. If no exit status
is specified, then $? is set to zero (true).
0 Success
The exit status is extremely important for programmers. They use it to devise program logic that
branches into different paths depending on the success or failure of a command.
1. &&
2. ||
2. cmd1 || cmd2
The && delimits two commands. The command cmd2 is executed only when cmd1 succeeds.
&& operator can be used along with grep as follows:
The || operator plays an inverse role. The second command is executed only when the first fails.
If you “grep” a pattern from a file without success, you can notify the failure:
The && and || operators are recommended for making simple decisions.
The if Conditional
The if statement makes two-way decisions depending on the fulfillment of a certain condition. In
the shell, the statement uses the following forms:
if command is successful
then
execute commands
else
execute commands
fi
Form 1
if command is successful
then
execute commands
fi
Form 2
if command is successful
then
execute commands
then …
else ….
fi
Form 3
if also requires a then. It evaluates the success or failure of the command that is specified in it’s
command line. If command succeeds, the sequence of commands following it is executed. If
command fails, then the else statement (if present) is executed. Ever if is closed with a
corresponding fi.
#!/bin/sh
then
else
fi
emp3.sh
In the script emp3.sh, grep is first executed and simple if-else construct tests the exit status of
grep.
$ emp3.sh ftp
ftp:*:325:15:FTP Users:/users1/home/ftp:/bin/true
$ emp3.sh mail
case expression in
pattern1) commands1 ;;
pattern2) commands2 ;;
pattern3) commands3 ;;
…………
esac
case first matches expression with pattern1. If the match succeeds, then it executes commands1,
which may be one or more commands. If the match fails, then pattern2 is matched and so forth.
Each command list is terminated with a pair of semicolons, and the entire construct is closed
with esac (reverse of case)
Consider a simple script menu.sh that uses case. The script accepts values from 1 to 5 and
performs some action depending on the number keyed in. The five menu choices are displayed
with a multi-line echo statement:
case matches the value of $choice with the strings 1,2,3,4 and 5. If the user enters a 1, the ls –l
command is executed. Option 5 quits the program. The last option (*) matches any option not
matched by the previous options.
#!/bin/sh
# menu.sh
echo “ MENU\n”
read choice
case “$choice” in
1) ls –l ;;
2) ps –f ;;
3) date ;;
4) who ;;
5) exit ;;
esac
menu.sh
$ menu.sh
MENU
1.List of files
2.Processes of user
3.Today’s date
4.Users of system
5.Quit to UNIX
expr
expr command combines two functions in one:
2. Manipulate strings
Computation
expr can perform the four basic aithmetic operations as well as the modulus(remainder) function.
$ x=3 y=5
$ expr 3+5
$ expr $x - $y
-2
$ expr 3 \* 5
15
$ expr $y / $x
$ expr 13 % 5
The operand such as +,-,*,etc must be enclosed on either side by whitespace. The multiplication
operand(*) has to be escaped to prevent shell from interpreting it as the filename metacharacter.
Since, expr can handle only integers, division yields only the integral part. expr is often used
with the command substitution to assign a variable. For example, user can set a variable z to the
sum of two numbers:
$ echo $z
$ x=5
$ x=`expr $x + 1`
$ echo $x
String Handling
2. Extract a substring
The length of a String : The regular expression .* signifies to expr that it has to print the number
of characters matching the pattern. i.e the length of the entire string.
12
In above example, expr has counted the number of occurrences of any character (.*) This feature
is useful in validating data entry.
Extracting a Substring – expr can extract a string enclosed by the escaped characters \ (and \) . If
user wish to extract the 2-digit year from a 4-digit string, then he must create a pattern group and
extract it in following way:
$ stg=2003
03
Locating Position of a Character – expr also return the location of the first occurrence of a
character inside a string. To locate the position of the character d in the string value of $stg, user
has to count the number of characters which are not d ([^d]*), followed by a d:
while Looping
The while statement repeatedly performs a set of instructions until the control command returns a
true exit status. The general syntax of this command is as follows:
do
commands
done
The commands enclosed by do and done are executed repeatedly as long as condition remains
true.
There are situations when a program needs to read a file that is created by another program, but it
also has to wait until the file is created. The script, monitfile.sh periodically monitors the disk
for existence of the file and then executes the program once the file has been located. It makes
use of the external sleep command that makes the script pause for the duration(in seconds) as
specified in the argument. The loop executes repeatedly as long as the file invoice.lst can’t b
read.If the file becomes readable, the loop is terminated and the program alloc.pl is executed.
#!/bin/sh
# monitfile.sh
while [ ! -r invoice.lst]
do
sleep 60
done
alloc.pl
monitfile.sh
do
commands
done
The loop body also uses the keywords do and done, but the additional parameters here are
variable and list.Each whitespace-separated word in list is assigned to variable in turn and
commands are executed until list is exhausted.
Example:
> done
The list here comprises a series of character strings (chap20 and onwards, representing
filenames) separated by whitespace. Each item in the list is assigned to the variable file. file first
gets the value chap20, then chap21, and so on. Each file is copied with a .bak extension and the
completion message displayed after every file is copied.
This feature is useful when used with commands that don’t accept filename as arguments (like
mailx command). If the message is short, you can have both the command and message in the
same script.
MARK
The here document symbol (<<) is followed by three lines of data and a delimiter (the string
MARK). The shell treats every line following the command and delimited by MARK as input to
the command. sharma at the other end will see the three lines of message text with the date
inserted by command substitution and the evaluated filename.
Many commands require input from the user. It is the same input that is keyed in, in response to
a series of questions posed by the command. For instance, user may have to enter a y two or
three times when the command pauses, but the questions may not come in quick succession.
Rather than wait for the prompt, we can instruct the script to take input from a here document.
We can make the script work noninteractively by supplying the inputs through a here document:
> director
> emp.lst
> END
Enter the pattern to be searched: Enter the file to be used : Searching for director from file
emp.lst
set
The set command is used for extracting fields from output. set assigns its arguments to the
positional parameters $1,$2 and so on. This feature is especially useful for picking up individual
fields from output of a program. set is used to convert its arguments to positional parameters.
$_
This assigns the value 9876 to the positional parameter $1, 2345 to $2 and 6213 to $3. It also
sets the other parameters $# and $*. User can verify this by echoing each parameter in turn:
Command substitution can be used to extract individual fields from the date output as follows:
$ set `date`
$ echo $*
When a script is sent any of the signals in signal_list, trap executes the commands in
command_list. The signal list can contain the integer values or names of one or more signals.
If you habitually create temporary files named after the PID number of the shell, you should use
the services of trap to remove them whenever an interrupt occurs.
trap ‘rm $$* ; echo “Program interrupted” ; exit’ HUP INT TERM
trap is a signal handler. It first removes all files expanded from $$*, echoes a message and
finally terminates the script when the signals SIGUP(1),SIGINT(2) or SIGTERM(15) are sent to
the shell process running the script. When the interrupt key is pressed, it sends the signal number
2.
The script valcode.sh uses the set and shift features to accept and validate a department code. It
looks up a code list maintained as a here document in the script file itself, and flashes the
department name on the terminal. Since echo always produces a true exi status, the statement
issuing the prompt is itself used as the control command of the while loop. The pattern selected
by grep is split by set on the | into three positional parameters. This is done by changing the IFS
setting that normally consists of whitespace. shift 3 flushes the positional parameters before
starting the next iteration.
#!/bin/sh
read dcode
01|accounts|6213
02|admin|5423
03|marketing|6521
04|personnel|2365
05|production|9876
06|sales|1006
case $# im
esac
done
valocde.sh
$ valcode.sh
Invalid code
The script doesn’t terminate normally, but user can use the interrupt key at any time to abort the
program.
dentry1.sh accepts a designation code and its description from the terminal, performs some
rudimentary validation checks, and then adds an entry to a file (design.lst). It validates the code
entered with the ones that already exist in the file. The script repeatedly prompts the user until
the right response is obtained.
The script prompts for two fields,the designation code and description, and uses two while loops,
one enclosed by the other. The code has to be reentered if it exists in the file or if it doesn’t have
a two-digit structure. Similarly the description has to be reentered if it contains a nonaplhabettic
character other than a space (*[!\ a-zA-Z]*). The continue statement lets user to reenter the data
or start a fresh cycle. The break statement in the inner loop quits the loop after ending the line.
$ cat design.lst
01| accounts
02| admin
03| marketing
04| personnel
05| production
06| sales
$ dentry1.sh
Designation code: 01
Code exists
Designation code:07
Designation code: 8
Invalid code
Designation code: 08
Normal exit
#!/bin/sh
# dentry1.sh
trap ‘echo Signal received ; exit’ HUP TERM # but these two signals will
file=design.lst
read design
fi ;;
continue ;;
esac
read desc
case “$desc” in
*[!\ a-zA-Z]*) echo “Can contain only alphabets and spaces” >/dev/tty
continue;;
*) echo “$desig|$desc”
esac
read answer
case “$answer” in
esac
done
dentry1.sh