قالب وردپرس درنا توس
Home / Tips and Tricks / Bash Functions and Local Variables – CloudSavvy IT

Bash Functions and Local Variables – CloudSavvy IT



Shutterstock

This article shows how local variable functions are used and created in Bash. Creating Bash functions can make your code more structural, and local variables help with security and prevent coding errors. Dive in!

What are Bash functions?

As with other coding languages, Bash allows you to create functions from your code or script. A function can be defined to perform a specific task or set of tasks, and can be easily and conveniently called from your main code simply by using the name given to the function.

You can also nest function calls (call a function from another function), use local variables within the function, and even pass variables back and forth with functions, or by using global variables. Let̵

7;s investigate.

Simple Bash function

We define a test.sh with our text editor, as follows:

#!/bin/bash

welcome(){
echo "welcome"
}

welcome

Then we make that file executable by executing the execute (x) property, and run the script:

chmod +x test.sh
./test.sh

A simple Bash function

We can see how the script first takes a welcome() function using the Bash idioms function_name(), and {} function wrappers. Finally, we call the feature welcome by simply using its name, welcome.

When the script is running, what happens in the background is the function definition is noted, but skipped (i.e. not executed), until the function call is a little lower welcome is hit and at what point the Bash interpreter uses the welcome function and returns to the line immediately after the function is called next, which is the end of our script in this case.

Pass variables to Bash functions

We define a test2.sh with our favorite text editor (vi;), like this:

#!/bin/bash

if [ -z "${1}" ]; then 
  echo "One option required!"
  exit 1
fi

func1(){
  echo "${1}"
}

func2(){
  echo "${2} ${1}"
}

func1 "${1}"
func2 "a" "b"

We make our script executable again chmod +x test2.sh and do the same.

A more advanced Bash feature with variable passes

The resulting output can look interesting or even confusing at first. However, it makes sense and is easy to follow. The first option passed to the script will be available globally from code as ${1}, except indoor functions, true ${1} becomes the first parameter passed to the function, ${2} the second etc.

In other words, the global ${1} variable (the first option passed to the script from the command line) is not available from functions, where the meaning of the ${1} variable changes to the first option passed to the function. Think hierarchy, or think how a function on its own could present a small script and this will quickly make sense.

One could also use as a sidenote $1 instead of ${1}, but I strongly encourage aspiring Bash coders to always surround variable names with { and }.

This is because the Bash interpreter is sometimes unable to use variables in a string see where a variable ends and some of the adjacent text can be taken as part of the variable name where it doesn’t, resulting in unexpected output. It is also cleaner and clearer what the intent is, especially when it comes to arrays and special option flags.

So we start our program with the global one ${1} variable set to "first". If you look at the calling of func1, you will see that we pass that variable to the function, so the ${1} within the function, what is in the ${1} of the program, ie "first", and therefore the first line of output is indeed first.

We will then call func2 and we pass two strings "a" and "b" to the position. These then become the ${1} and ${2} automatically in the func2 function. Within the function, we print them in reverse, and our output matches nicely b a as the second line of output.

Finally, we also do a check at the top of our script that ensures that an option is actually passed to it test2.sh script by checking if "${1}" is empty or uses the -z test within the if order. We leave the script with a non-zero exit code (exit 1) to indicate to calling programs that something has gone wrong.

Local variables and recurring values

For our last example, we define a test3.sh script as follows:

#!/bin/bash

func3(){
  local REVERSE="$(echo "${1}" | rev)"
  echo "${REVERSE}"
}

INPUT="abc"
REVERSE="$(func3 "${INPUT}")"
echo "${REVERSE}"

We make it executable again and run the script. The output is cba as can be expected by scanning the code and noting the variable names etc.

Example with local variables and recurring values

However, the code is complex and takes some getting used to. Let’s investigate.

First we define a function func3 in which we create a local variable named REVERSE. We assign a value to it by a subshell ($()), and from this subshell we echo whatever passed to the function (${1}) and route this output to the rev order.

The rev command prints the input received from the pipe (or otherwise) in reverse order. Also interesting to note here is that the ${1} variable stays in the subshell! It is completely over.

Then still from it func3 function, we print the output. However, this output is not sent to the screen, but is captured by our function call itself and thus stored in it ‘global’ REVERSE variable.

We prepare our input "abc", call the func3 function from a subshell, where the INPUT variable and assign the output to the REVERSE variable. Note that there is absolutely no relationship between the ‘global’ REVERSE variable and the local REVERSE variable in the script.

While any global variable, including any REVERSE is passed to the function, once a local variable with the same name is defined, the local variable is used. We can also prove this and see another little script test4.sh:

#!/bin/bash

func3(){
  local REVERSE="$(echo "${1}" | rev)"
  echo "${REVERSE}"
}

INPUT="abc"
REVERSE="test"
func3 "${INPUT}"
echo "${REVERSE}"

Bash function and example of a local variable illustrating two of the learning points seen so far

At execution is output cba and test. The cba is generated by the same this time echo "${REVERSE}" inside the func3 function, but this time it runs directly instead of being recorded in the code below as the func3 "${INPUT}" function is not called from a subshell.

This script highlights two learning points that we covered earlier: first, that – even though we have the REVERSE variable to "test" in the script before running the func3 function – that the local variable REVERSE takes over and is used in place of the ‘global’ a.

Second, that our ‘global’ REVERSE variable retains its value, even if there was one local variable with the same name that is used from the called function func3.

Shut down

As you can see, Bash functions, passing variables, and using local and semi-global variables make the Bash scripting language versatile, easy to code, and allows you to define well-structured code.

Also noteworthy to mention here is that in addition to improved code readability and ease of use, the use of local variables provides additional security as variables cannot be accessed outside the context of a function etc. Enjoy functions and local variables while coding in Bash!

If you’d like to learn more about Bash, check out our How to properly parse filenames in Bash, and use xargs in conjunction with bash -c to create complex commands.


Source link