Learn more about SQL Server tools

mssqltips logo
 

Tutorials          DBA          Dev          BI          Career          Categories          Webcasts          Whitepapers          Today's Tip          Join

Tutorials      DBA      Dev      BI      Categories      Webcasts

DBA    Dev    BI    Categories

 

Introduction to Bash Scripting: Functions


By:   |   Last Updated: 2018-12-31   |   Comments   |   Related Tips: More > SQL Server on Linux

Problem

If you have read my previous tips of this series about Bash Scripting, you are probably curious about code reusability in a Bash Script. In this tip I will introduce you to Bash functions.

Solution

Every time someone faces a complex situation, there is a well-known phrase from Julius Cesar, that most of the time the best way to find the solution is to "Divide and conquer". This principle is the key to what is called Modular Programming, which is a paradigm based on subdividing a program into separate parts or modules.

The fact of dividing a program into smaller parts has many benefits:

  • It makes it easier to understand the program, because you look at one execution unit (subprogram) at a time.
  • It allows code reusability, because you can invoke each subprogram in many different parts of the code and even in other subprograms. It is a subprogram invoking a subprogram.
  • It provides layers of abstraction. You can have a subprogram named "ShowMessageToUser" that shows a given message to the user and you can invoke it without even knowing the code.
  • It makes the program easier to maintain.

If you want to implement modular programming in a Bash script you have two ways of doing it. Either you split your script into smaller sets of code or you use functions.

Functions in Bash Scripts

Declaring a function in a Bash script is very straightforward. Take a look at its structure.

function [FunctionName] {
 ...
 [return ReturnValue]
}

As you can see, in order to declare a function you only need to use the "function" keyword and specify a function name, then include the code between brackets. You don't need to define a function header or declare its arguments. Something important to note is that functions do not need to return data. I make this clarification because maybe you have some experience in programming and in some programming languages functions must return a value, one of those languages is Transact-SQL. For bash, the concept of functions is more related to the C language concept of functions when functions can return a void type which means that they don't return anything. Other languages like Visual Basic and Pascal differentiate between functions and subroutines (or procedures in Pascal) so functions always return something in opposition to subroutines that don't return anything.

Since an example is worth a thousand words, let's view some examples of functions.

Example Bash Functions

Let's start with a very basic function:

#!/bin/bash

echo "This is your first function!:"

function MyFirstFunction() {
echo $1
}

MyFirstFunction "Hello World!"

From the code above, before using the function we must first declare it. I know it seems pretty obvious, but I make this clarification because there are languages like VBScript that allow using a function or procedure before its declaration.

Returning to the function, it only echoes the first parameter passed to the function which is identified as $1. You can access each parameter by using the dollar sign followed by a number that correlates to the parameters order (i.e. $1 is the first parameter, $2 is the second parameter, $n is the nth parameter). If you are curious about what returns $0, well it returns the name of the script.

On the next screen capture you can see the output of the previous script execution.

Execution of a simple function.

Another thing to note is that you can pass more than one parameter to the function "MyFirstFunction" even when the function only uses one and you won't receive any errors. Take a look.

#!/bin/bash

echo "This is your first function!:"

function MyFirstFunction() {
echo $1
echo $0
}
MyFirstFunction "Hello World!" "What?" "Really?"?

I slightly changed the function "MyFirstFunction" and added a line to show (echo) the $0 parameter. Additionally, I called the function with three parameters. As you can see in the next image, contrary to what we expect, there were no errors in the execution.

No errors passing more parameters than used.

Another interesting thing that you can see on the previous image is that the "echo $0" result changed when we used the relative path and the full path.

Now let's do a more complex function. The next script declares a function named "sum" that returns the sum of two numbers. Take a look.

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "you entered..."
echo $1 " = " $(($1))
echo $2 " = " $(($2))

    echo "Result of" $1 + $2 "is:" $(($1 + $2))

}

read -p "Enter first number: " Num1
read -p "Enter second number: " Num2

sum Num1 Num2

On the next screen capture you can see the result of the execution of the previous script.

Sum of two numbers.

I am not a wizard, just a DBA, but let me guess what the most confusing part of this script is:

echo $1 " = " $(($1))

If you have been reading my previous tips in this series and had the chance to read the tip about declaration of variables and constants you may remember that I gave you a "rule of thumb". Anyways I will rewrite that rule here: "If you are writing a script and need to refer to the value of a variable and not to the variable itself just put a dollar sign in front of it". Well, that rule still applies. And the double parenthesis enclosing $1 are what is called an "Arithmetic Expansion". There is another notation for arithmetic expansions which consists of using single brackets instead of double parenthesis. The following expressions are equivalent.

echo $1 " = " $(($1))
#both expressions are equal
echo $1 " = " $[$1]			

I have rewritten the previous script by using brackets instead of double parenthesis.

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "you entered..."
echo $1 " = " $[$1]
echo $2 " = " $[$2]
    echo "Result of" $1 + $2 "is:" $[$1 + $2]
}
read -p "Enter first number: " Num1
read -p "Enter second number: " Num2

sum Num1 Num2

As you can see on the image below, using single brackets instead of double parenthesis has the same result.

Arithmetic Expansion.

Now what if I change the way I call the sum function and instead of passing as arguments Num1 and Num2, I pass $Num1 and $Num2 like the following code?

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "you entered..."
echo $1 " = " $(($1))
echo $2 " = " $(($2))

    echo "Result of" $1 + $2 "is:" $(($1 + $2))

}

read -p "Enter first number: " Num1
read -p "Enter second number: " Num2

sum $Num1 $Num2

On the next screen capture you will see the result of executing the previous script.

A little change in the script changes the whole result.

As you can see on the previous image, passing the argument preceded with a dollar sign (i.e. $Num1 instead of Num1) allows us to avoid using arithmetic expansion. This is because we are not passing the variable as an argument to the function; instead we are passing the variable's value.

And now, what if we change the script a little bit and instead of summing two variables we concatenate two strings. I am passing the parameters to the function without preceding them with a dollar sign. Do we need arithmetic expansion? What do you think? Take a look at the next script.

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "The result is...: " $1 $2
}

Text1="hello"
Text2="World"

sum Text1 Text2

As you can see on the image below, we didn't have the outcome we expected. By passing Text1 and Text2 variables to the sum function without using a preceding dollar sign resulted in a concatenation of both variable names, not its contents.

Trying to concatenate text with no success.

And what if we use the arithmetic expansion? Take a look at the next script.

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "The result is...: " $(($1)) $(($2))
}

Text1="hello"
Text2="World"

sum Text1 Text2

On the next image you will see that we also didn't have the desired result (i.e. we want that the result be "Hello World"). But the outcome of using arithmetic expansion is that writing to the screen those variables gives us as a result a zero for each variable instead of the variable name (i.e. Text1 and Text2). If you think about it, that's the result we must have because we are doing an arithmetic expansion on a text. In layman's terms, it is like comparing pears with apples.

Arithmetic Expansion doesn

Finally, let's take a look at the next script that will do what is expected (i.e. write "Hello World" to the console).

#!/bin/bash

echo "Let's do a sum function!:"

function sum() {
echo "The result is...: " $1 $2
}

Text1="hello"
Text2="World"

sum $Text1 $Text2

On the next screen capture you will see that we succeeded in our goal, but why? The answer relies on the dollar sign in front of the variables Text1 and Text2 when we called the function. Remember the "rule of thumb"?: "If you are writing a script and need to refer to the value of a variable and not to the variable itself just put a dollar sign in front of it.". What we did by putting the dollar sign is like writing the text instead of the variable like follows.

sum $Text1 $Text2
# Is like writing 
sum "Hello" "World"
This is the proper way to use text variables as parameters to a function.
Next Steps


Last Updated: 2018-12-31


next webcast button


next tip button



About the author
MSSQLTips author Daniel Farina Daniel Farina was born in Buenos Aires, Argentina. Self-educated, since childhood he showed a passion for learning.

View all my tips
Related Resources




Post a comment or let the author know this tip helped.

All comments are reviewed, so stay on subject or we may delete your comment. Note: your email address is not published. Required fields are marked with an asterisk (*).

*Name    *Email    Email me updates 


Signup for our newsletter
 I agree by submitting my data to receive communications, account updates and/or special offers about SQL Server from MSSQLTips and/or its Sponsors. I have read the privacy statement and understand I may unsubscribe at any time.



    



Learn more about SQL Server tools