Decisions
We continue with the topic of decisions in this section.Else
File: else1.sh
var1=1 if [ $var1 -gt 9 ] then echo "var1 is greater than 9" else echo "var1 is less than 9" fi Output: $ ./else1.sh var1 is less than 9 The above shows the "else" statement that is executed if the "if" condition is false. We can also have "elif" statement .
File: else12.sh
var1=11 if [ $var1 -gt 19 ] then echo "var1 is greater than 9" elif [ $var1 -eq 11 ] then echo "var1 is euqal to 11" fi Output: $ ./else2.sh var1 is euqal to 11 Case statement Similar to "if" we can have a "case" statement.
File: case1.sh
if [ "$#" -ne 1 ] then echo "Usage: number digit" exit 1 fi case "$1" in 0) echo zero;; 1) echo one;; 2) echo two;; 3) echo three;; 4) echo four;; 5) echo five;; 6) echo six;; 7) echo seven;; 8) echo eight;; 9) echo nine;; esac Output: $ ./case1.sh Usage: number digit $ ./case1.sh 2 two $ ./case1.sh 4 four The ";;" indicates that we should break out of the case statement.
File: case2.sh
if [ "$#" -ne 1 ] then echo "Usage: number" exit 1 fi case "$1" in [0-9]) echo "Single Digit Number" ;; [0-9][0-9]) echo "Two Digit Number" ;; [0-9][0-9][0-9]) echo "Three Digit Number" ;; *) echo "Something else." ;; esac Output: $ ./case2.sh 5 Single Digit Number $ ./case2.sh 56 Two Digit NumberLoops
We can have loops in Shell scripting. There are many variations of the for loop: 1)
File: loop1.sh
for i1 in 1 2 3 do echo $i1 done Output: $ ./loop1.sh 1 2 3 In the "for some variable in" we provide a list of constants. The variable will take on the value of each of the constants and output the value using "echo" . The statements between the "do" and "done" are executed with each iteration. We can also replace the "do" and "done" with curly braces .
File: loop2.sh
for i1 in 1 2 3 { echo $i1 } $ ./loop2.sh 1 2 3 We can also have the for loop with the syntax as:
File: loop3.sh
for i1 in {1..5} do echo "$i1" done $ ./loop3.sh 1 2 3 4 5 We can also specify a step value in the for loop :
File: loop4.sh
for i1 in {1..10..2} do echo "$i1" done $ ./loop4.sh 1 3 5 7 9 Here the value of 1 is incremented by 2 till it is greater than 10 and at that time the loop exits. We can also use shell wildcards in a for loop. A shell wildcard is expanded to say the file.
File: loop5.sh
for i1 in * do echo "$i1" done $ ./loop5.sh 1 case1.sh case2.sh else1.sh else2.sh ... In the above all the files become the values for i1. Break and Continue The "break" keyword breaks out of a for loop.
File: loop6.sh
for i1 in 1 2 3 4 5 do echo "$i1" if [ $i1 -eq 3 ] then break fi done echo "End of for loop." Output: $ ./loop6.sh 1 2 3 End of for loop. The "continue" keyword continues to the beginning of the for loop. The lines in the block after the "continue" statement are not executed.
File: loop7.sh
for i1 in 1 2 3 4 5 do if [ $i1 -eq 3 ] then continue fi echo "$i1" done echo "End of for loop." Output: $ ./loop7.sh 1 2 4 5 End of for loop. We can see that when "$i1" was equal to 3 the echo statement at the bottom was skipped. Basically the body after the "continue" is skipped.Arguments
We can pass arguments to our shell scripts.The command "who" lists all the users that are logged in. The below script checks
File: arg1.sh
who | egrep "$1" $ ./arg1.sh amittal amittal pts/0 2024-04-07 10:57 (99.7.60.213) In order to make the script a bit more user friendly we can put a check to see if an argument was given.
File: arg2.sh
if [ $# -ne 1 ] then echo "Wrong number of Arguments. Enter username." exit 1 fi who | egrep "$1" $ ./arg2.sh Wrong number of Arguments. Enter username. The string "$#" denotes the number of arguments passed to the string. The actual argument value can be obtained for the first argument as "$1" and for the second argument as "$2" and so on.
File: arg3.sh
echo "$*" $ ./arg3.sh first second third first second third The "shift" command. The shift command will reduce the value of "$#" by one and the value of "$3" will be stored into "$2".
File: arg4.sh
echo $# $* shift echo $# $* $ ./arg4.sh a b c 3 a b c 2 b c After the "shift" operation the number of arguments has reduced to 2.
File: arg5.sh
echo $0 $1 shift echo $0 $1 $ ./arg5.sh a b c ./arg5.sh a ./arg5.sh b In the above "$0" denotes the name of the script. Exercise Write a shell script called "c1.sh" . Ask a user to enter 3 parameters. If the user does not enter 3 parameters then print an error message and exit the program. Take the first 2 arguments to be the names of files and concatenate them using the "cat" command to place the output in the third argument.Functions
We can have functions in a shell script.
File: func1.sh
isEvenOdd() { #echo "Step2 $1" if [ `expr $1 % 2` -eq 0 ] then #echo "Step3" return 1 else return 0 fi } #echo "Step1 $1" NO_TO_TEST=3 isEvenOdd $NO_TO_TEST #echo $? if [ $? -eq 1 ] then echo "$NO_TO_TEST is an even number" else echo "$NO_TO_TEST is an odd number" fi $ ./func1.sh 3 is an odd number The function is defined without any parameters. It takes the parameters the same way we pass parameters to the shell using the dollar symbol. In the above code we have written a function called "isEvenOdd" that checks whether the argument is even or odd. It uses the "return" function to return a code. We can obtain this code in the calling place using the "$?" symbol which signifies the return code of executing the function. We need to use this right after we call the function else we might end up with the return code of the functions/commands in the middle. We can also pass in the argument through command line when calling the script.
File: func2.sh
isEvenOdd() { #echo "Step2 $1" if [ `expr $1 % 2` -eq 0 ] then #echo "Step3" return 1 else return 0 fi } #echo "Step1 $1" NO_TO_TEST=$1 isEvenOdd $NO_TO_TEST #echo $? if [ $? -eq 1 ] then echo "$NO_TO_TEST is an even number" else echo "$NO_TO_TEST is an odd number" fi $ ./func2.sh 24 24 is an even number In the above example we pass in the value to test as an argument to the shell script.
File: func3.sh isEvenOdd() { #echo "Step2 $1" if [ `expr $1 % 2` -eq 0 ] then #echo "Step3" return 1 else return 0 fi } #echo "Step1 $1" NO_TO_TEST=$2 isEvenOdd $NO_TO_TEST #echo $? if [ $? -eq 1 ] then echo "$NO_TO_TEST is an even number" else echo "$NO_TO_TEST is an odd number" fi NO_TO_TEST=$1 isEvenOdd $NO_TO_TEST #echo $? if [ $? -eq 1 ] then echo "$NO_TO_TEST is an even number" else echo "$NO_TO_TEST is an odd number" fi $ ./func3.sh 12 13 13 is an odd number 12 is an even number Notice that in the above the function is taking the argument passed to it using "$1" . So the "$1" inside the function does not refer to the argument passed to the script but the argument passed to it when we call the function.
File: func4.sh HOMEDIR="" getHomeDir() { HOMEDIR=`cat /etc/passwd | grep amittal` #amittal:x:2548:1258:Ajay MIttal:/users/amittal:/bin/bash HOMEDIR=`echo $HOMEDIR | cut -f6 -d:` } USER=$1 getHomeDir $USER echo $HOMEDIR $ ./func4.sh amittal /users/amittal In the above script we want to pass in a user name and obtain the home directory for that user. Our function is using a global variable to pass in the value to the main part of the script. Notice the use of back quotes to assign the output of the command to a variable.
File: func5.sh #!/bin/bash # Define a function named get_user function get_user { echo $USER } # Call the get_user function and capture # the result in the variable "username" username=$(get_user) # Print a message using the value stored # in the "username" variable echo "Hello, $username!" The above example shows how we can use "echo" to return a string from the function.