Welcome to part 3 of Bash Shell Scripting at a beginner level. This final article will look at a few more items that will get you primed for your continued personal development. It will touch on functions, using comparisons with if/elif statements, and will wrap up with looking into the while loop.
Functions
Let’s start out with a basic concept that might seem difficult but is really simple, the function. Think of this as a simple way to put a part of a script that is used over and over into one reusable group. Anything you have done in article 1 or 2 can be put into a function. So let’s put a function into our learnToScript.sh file. Let me point out a few things. You will need a name for your function, the opening and closing parentheses, and curly brackets to enclose the commands that are included in your function.
#!/bin/bash #A function to return an echo statement. helloFunc() { echo "Hello from a function." } #invoke the first function helloFunc() helloFunc
Below you will see the output.
[zexcon@fedora ~]$ ./learnToScript.sh Hello from a function. [zexcon@fedora ~]$
Functions are a good way to reuse a group of commands but they can be even more useful if you can make them operate on different data each time they are used. This requires that you provide data, referred to as arguments, to the function each time you call it.
To provide arguments, you simply add them after the function name when you invoke it. To use the data you provide, you use the positional references in the function commands. They will be named $1, $2, $3, and so on, depending on the number of arguments your function will need.
Let’s modify the last example to help understand this better.
#!/bin/bash #A function to return an echo statement. helloFunc() { echo "Hello from a function." echo $1 echo $2 echo "You gave me $# arguments" } #invoke the function helloFunc() helloFunc "How is the weather?" Fine
The output is shown below.
Hello from a function. How is the weather? Fine You gave me 2 arguments
What is happening in the output is helloFunc() did an echo on each line. First it does an echo of “Hello from a function”, then it moves to echo the value of variable $1, this is the result of what you passed to helloFunc with “How is the weather?”. It will then move onto variable $2 and echo its value that is the second item you passed “Fine”. The function will finish by returning the echo “You gave me $# arguments”. Notice that the first argument was a single string enclosed in double quotes, “How is the weather?” . The second one, “Fine”, had no spaces so the quotes where not needed.
In addition to using $1, $2, etc. you can determine the number of arguments being passed to the function by using the variable $#. This means that you can create a function which accepts a variable number of arguments.
There are many good references on line for more details on bash functions. Here is one to get you started.
I hope you can see how functions can provide great flexibility in your bash scripts.
Numeric comparisons []
If you want to do a numerical comparison you will need to use one of the following operators between square brackets [] .
-eq (is equal)
-ge (equal or greater than)
-gt (greater than)
-le (less than or equal)
-lt (less than)
-ne (not equal)
So for example if you wanted to see if 12 is equal to or less than 25 it would you like [ 12 -le 25 ]. The 12 and 25, of course, can be variables. For example, [$twelve -le $twentyfive].
if and elif Statement
So let’s use our numerical comparison to introduce the if statement. An if statement in Bash will start with if and end with fi. You start with the if followed by the check you are wanting to do. In this case the check will be is variable numberOne equal to 1. If numberOne is equal to 1 it will execute the then statement, otherwise it will execute the else statement.
#!/bin/bash numberTwelve=12 if [ $numberTwelve -eq 12 ] then echo "numberTwelve is equal to 12" elif [ $numberTwelve -gt 12 ] then echo "numberTwelve variable is greater than 12" else echo "neither of the statemens matched" fi
The output for that follows:
[zexcon@fedora ~]$ ./learnToScript.sh numberTwelve variable is equal to 12
What you are seeing is the first line in the if statement checking to see if the variables value is really equal to 12. If it is the statement stops and echos “numberTwelve is equal to 12” and execution of your script will continue after the fi. If the variable was greater then 12 it would have executed the elif statement and again continued execution after the fi. When you use an if or if/elif statement it works from the top down. When the first statement is a match it stops and executes that command and continues after the fi.
String comparisons [[]]
So that was numeric comparisons. What about comparing strings? Uses the double square brackets [[]] and the following operators equal or not equal.
= (equal)
!= (not equal)
Keep in mind strings have several other comparisons that we will not discuss but dig in and read about them and how they work.
#!/bin/bash #variable with a string stringItem="Hello" #This will match since it is looking for an exact match with $stringItem if [[ $stringItem = "Hello" ]] then echo "The string is an exact match." else echo "The strings do not match exactly." fi #This will utilize the then statement since it is not looking for a case sensitive match if [[ $stringItem = "hello" ]] then echo "The string does match but is not case sensitive." else echo "The string does not match because of the capitalized H." fi
You will get the following three lines.
[zexcon@fedora ~]$ ./learnToScript.sh The string is an exact match. The string does not match because of the capitalized H. [zexcon@fedora ~]$
While Loop
Let’s take a look at a loop before wrapping up the series. An example of the while loop is “while 1 is less then 10 add one to the value” you continue doing this until it is no longer true. Below you will see the variable number set to 1. On the next line we have the while statement that does a check to see if number is less then or equal to 10. The commands contained between do and done are executed since the while comparison is true. so we echo some text and add one to the value of number. We continue until the while statement is no longer true and it breaks out of the loop and echo’s “We have completed the while loop since $number is greater than 10.”
#!/bin/bash number=1 while [ $number -le 10 ] do echo "We checked the current number is $number so we will increment once" ((number=number+1)) done echo "We have completed the while loop since $number is greater than 10."
The result of the while loop is the following.
[zexcon@fedora ~]$ ./learnToScript.sh We checked the current number is 1 so we will increment once We checked the current number is 2 so we will increment once We checked the current number is 3 so we will increment once We checked the current number is 4 so we will increment once We checked the current number is 5 so we will increment once We checked the current number is 6 so we will increment once We checked the current number is 7 so we will increment once We checked the current number is 8 so we will increment once We checked the current number is 9 so we will increment once We checked the current number is 10 so we will increment once We have completed the while loop since 11 is greater than 10. [zexcon@fedora ~]$
As you can see the amount of scripting needed to make this happen is much less then if you continued to check each number with an if statement. This is the great part of loops and the while loop is only the first of many options that do things differently to meet your personal needs.
Conclusion
What is next? As the article pointed out it’s Bash Shell Scripting for Beginners. Hopefully I sparked an interest or life long love for scripting. I recommend you check out other’s scripts and look up what you don’t know or understand. Remember that as each article presented more ways of doing math, comparing strings, outputting and imputing data they can also be done in functions, loops or numerous other ways. If you practice the basics discussed you will have a blast combining them with all the other options you are still going to learn. Go out and have fun and I’ll see you around the Fedora Linux world.
Michael
Really nice series of article. As a PHP developer looking to extend my knowledge into Linux scripting this articles were a great starting point!
Esc
Thank You
Hanku
Motivated to try out scripts, thanks.
Mario Lopez
Thanks for your time writing this excellent article, I learn very much this great time reading your notes !
HDR
Good article, well explained. Thank you.
claus blom
Thank you Matthew,
great Bash scripting lesson. I am retired and living in Turkey now. I like Linux and that command line. Sometimes I try to write little Bash or Python scripts.
I am not a programmer and that’s why I am always grateful if I can find nice examples in the word wide web.
Thanks again,
Claus
official site
so nice article Very thankful such as sahring impressive information with us
This is nice article I appreciate you for this kind of information. Thanks lot.
edier88
Hi. Thank you very much for the post. I’m following them all.
I really want to improve my skills in bash scripting. Thanks a lot!
Phoenix
The use of single and double-brackets is not entirely correctly depicted. The single bracket use can likewise compare strings as it can do numbers. So do double-brackets with numbers. The double-brackets are a newer, more modern approach, which adds the ability to compare regular expressions as well as allows string comparison without using quotes, which when using single-brackets can lead to errors when a variable holds an empty string.
So,
if [ "$a" = "asd" ]; then
is the same as
if [[ $a = asd ]]; then
in terms of the results.
The single-bracket notation is a shorthand for the command “test” (see “man 1 test”) while the double-bracket notation is a “bashism” (see “man 1 bash” and search for “Compound Commands”).
Gregory Bartholomew
And you don’t have to worry about the double-quotes with the newer double-bracket version — why would one ever go back to using the old version! 🙂
As an aside, I prefer to use == when doing comparisons to avoid the operation looking (or behaving!) like an assignment.
Phoenix
“why would one ever go back to using the old version!”
Short answer is: compatibility.
Longer explanation:
When writing scripts not necessarily relying on “bash” or if they include systems having versions of bash not (yet) sporting this notation.
Stathis
Well the article is named “bash shell scripting” so focusing on bash is not too bad of an idea. Compatibility with other shells would require a whole different set of posts.
Another argument for using double brackets is that double brackets are a bash built-in so invoking does not incur the overhead of calling an additional binary.
On the other hand, single brackets are an alias to the “test” command so on every comparison using single brackets another binary would have to be executed.
Double brackets have been part of bash for a very long time so unless you are targeting a very old system or have inherited some scripts from a bygone era there realle is no reason for not using them.
Leslie Satenstein, Montreal,Que,
Well done.
Thank you
Leslie
Shy
This:
is the same as this:
without the double quotes around the Hello.
Quotes are necessary to avoid splitting (embedded “whitespace” (really $IFS chars) ), missing positional parameters (if cmd requires an argument then this will fail: a=””; cmd $a), and globbing (this will show all the files in the current directory as * will expand: foo=* ; echo $foo).
Whether or not bash has strings is debatable.
Shy
This:
is the same as this:
without the double quotes around the Hello.
Quotes are necessary to avoid splitting (embedded “whitespace” (really $IFS chars) ), missing positional parameters (if cmd requires an argument then this will fail: a=””; cmd $a), and globbing (this will show all the files in the current directory as * will expand: foo=* ; echo $foo).
Whether or not bash has strings is debatable.
Phoenix
True for variable content containing whitespace characters. Though despite causing errors as positional parameters, variables holding an empty string (e.g.
) will work fine inside the double brackets compared to using single brackets, which in turn will flip with “unary operator expected” when done.
The basic idea of my comment above was simply to show that both, single and double brackets can do the same kind of comparison and is not – as outlined in the article – limited to algebra for one type of brackets and and strings for the other. I was therefore simplifying my examples to demonstrate.