Tag Archives | bash functions

Bash Scripting Part6 – Create and Use Bash Functions

Before we talk about bash functions, let’s discuss this situation. When writing bash scripts, you’ll find yourself that you are using the same code in multiple places. If you get tired of writing the same lines of code again and again in your bash script, it would be nice to write the block of code once and call it anywhere in your bash script. The bash shell allows you to do just that with Functions. Bash functions are blocks of code that you can reuse them anywhere in your code. Anytime you want to use this block of code in your script, you simply type the function name given to it. We are going to talk about how to create your own bash functions and how to use them in shell scripts.

Continue Reading →

Creating a function

You can define a function like this:

functionName() {

}

The brackets () is required to define the function.

Also, you can define the function using the function keyword, but this keyword is deprecated for POSIX portability.

function functionName() {

# Deprecated definition but still used and working

}

In the second definition, the brackets are not required.

Using Functions

#!/bin/bash

myfunc() {

echo "Using functions"

}

total=1

while [ $total -le 3 ]; do

myfunc

total=$(($total + 1))

done

echo "Loop finished"

myfunc

echo "End of the script"

Here we’ve created a function called myfunc and in order to call it, we just typed its name.

bash functions

The function can be called many times as you want.

Notice: If you try to use a function which is not defined, what will happen?

#!/bin/bash

total=1

while [ $total -le 3 ]; do

myfunc

total=$(($total + 1))

done

echo "Loop End"

myfunc() {

echo "Using function ..."

}

echo "End of the script"

call before declare

Oh, it’s an error because there no such function.

Another notice: bash function name must be unique. Otherwise, the new function will cancel the old function without any errors.

#!/bin/bash

myfunc() {

echo "The first function definition"

}

myfunc

function myfunc() {

echo "The second function definition"

}

myfunc

echo "End of the script"

override definition

As you can see, the second function definition takes control from the first one without any error so take care when defining functions.

Using the return Command

The return command returns an integer from the function.

There are two ways of using the return command; the first way is like this:

#!/bin/bash

myfunc() {

read -p "Enter a value: " value

echo "adding value"

return $(($value + 10))

}

myfunc

echo "The new value is $?"

return command

The myfunc function adds 10 to the  $value variable then show the sum using the $? Variable.

Don’t execute any commands before getting the value of the function, because the variable $? returns the status of the last line.

This return method returns integers. what about returning strings?

Using Function Output

The second way of returning a value from a bash function is command substitution. This way, you can return anything from the function.

#!/bin/bash

myfunc() {

read -p "Enter a value: " value

echo $(($value + 10))

}

result=$(myfunc)

echo "The value is $result"

bash functions output

Passing Parameters

We can deal with bash functions like small snippets that can be reused and that’s OK, but we need to make the function like an engine, we give it something and it returns a result based on what we provide.

You can use the environment variables to process the passed parameters to the function. The function name is declared as $0 variable, and the passed parameters are $1, $2, $3, etc.

You can get the number of passed parameters to the function using the ($#) variable.

We pass parameters like this:

myfunc $val1 10 20

The following example shows how to use the ($#) variable:

#!/bin/bash

addnum() {

if [ $# -gt 2 ]; then

echo "Incorrect parameters passed" # If parameters no equal 2

else

echo $(($1 + $2)) # Otherwise add them

fi

}

echo -n "Adding 10 and 15: "

value=$(addnum 10 15)

echo $value

echo -n "Adding three numbers: "

value=$(addnum 10 15 20)

echo $value

pass parameters

The addnum function gets the passed parameters count. If greater than 2 passed, it returns -1.

If there’s one parameter, the addnum function adds this parameter twice. If 2 parameters passed, the addnum function adds them together, and if you try to add three parameters it will return -1.

If you try to use the passed parameters inside the function, it fails:

#!/bin/bash

myfunc() {

echo $(($1 + $2 + $3 + $4))

}

if [ $# -eq 4 ]; then

value=$(myfunc)

echo "Total= $value"

else

echo "Passed parameters like this: myfunc a b c d"

fi

unknown parameters

Instead, you have to send them to the function like this:

#!/bin/bash

myfunc() {

echo $(($1 + $2 + $3 + $4))

}

if [ $# -eq 4 ]; then

value=$(myfunc $1 $2 $3 $4)

echo "Total= $value"

else

echo "Passed parameters like this: myfunc a b c d"

fi

bash functions parameters

Now it works!!

Processing Variables in Bash Functions

Every variable we use has a scope, the scope is variable visibility to your script.

You can define two types of variables:

  • Global
  • Local

Global Variables

They are visible and valid anywhere in the bash script. You can even get its value from inside the function.

If you declare a global variable within a function, you can get its value from outside the function.

Any variable you declare is a global variable by default. If you define a variable outside the function, you call it inside the function without problems:

#!/bin/bash

myfunc() {

input=$(($input + 10))

}

read -p "Enter a number: " input

myfunc

echo "The new value is: $input"

global variables

If you change the variable value inside the function, the value will be changed outside of the function.

So how to overcome something like this? Use local variables.

Local Variables

If you will use the variable inside the function only, you can declare it as a local variable using the local keyword  like this:

local tmp=$(( $val + 10 ))

So if you have two variables, one inside the function and the other is outside the function and they have the identical name, they won’t affect each other.

#!/bin/bash

myfunc() {

local tmp=$(($val + 10))

echo "The Temp from inside function is $tmp"

}

tmp=4

myfunc

echo "The temp from outside is $tmp"

local variables

When you use the $tmp variable inside the myfunc function, it doesn’t change the value of the $tmp which is outside the function.

Passing Arrays As Parameters

What will happen if you pass an array as a parameter to a function:

#!/bin/bash

myfunc() {

echo "The parameters are: $@"

arr=$1

echo "The received array is ${arr[*]}"

}

my_arr=(5 10 15)

echo "The old array is: ${my_arr[*]}"

myfunc ${my_arr[*]}

pass arrays

The function only takes the first value of the array variable.

You should disassemble the array into its single values, then use these values as function parameters. Finally, pack them into an array in the function like this:

#!/bin/bash

myfunc() {

local new_arr

new_arr=("$@")

echo "Updated value is: ${new_arr[*]}"

}

my_arr=(4 5 6)

echo "Old array is ${my_arr[*]}"

myfunc ${my_arr[*]}

pass arrays solution

The array variable was rebuilt thanks to the function.

Recursive Function

This feature enables the function to call itself from within the function itself.

The classic example of a recursive function is calculating factorials. To calculate the factorial of 3, use the following equation:

3! = 1 * 2 * 3

Instead, we can use the recursive function like this:

x! = x * (x-1)!

So to write the factorial function using bash scripting, it will be like this:

#!/bin/bash

fac_func() {

if [ $1 -eq 1 ]; then

echo 1

else

local tmp=$(($1 - 1))

local res=$(fac_func $tmp)

echo $(($res * $1))

fi

}

read -p "Enter value: " val

res=$(fac_func $val)

echo "The factorial of $val is: $res"

bash recursive function

Using recursive bash functions is so easy!

Creating Libraries

Now we know how to write functions and how to call them, but what if you want to use these bash functions or blocks of code on different bash script files without copying and pasting it on your files.

You can create a library for your functions and point to that library from any file as you need.

By using the source command, you can embed the library file script inside your shell script.

The source command has an alias which is the dot. To source a file in a shell script, write the following line:

. ./myscript

Let’s assume that we have a file called myfuncs that contains the following:

addnum() {

echo $(($1 + $2 + $3 + $4))

}

Now, we will use it in another bash script file like this:

#!/bin/bash

. ./myfuncs

result=$(addnum 10 10 5 5)

echo "Total = $result"

source command

Awesome!! We’ve used the bash functions inside our bash script file, we can also use them in our shell directly.

Use Bash Functions From Command Line

Well, that is easy, if you read the previous post which was about the signals and jobs you will have an idea about how to source our functions file in the bashrc file and hence we can use the functions directly from the bash shell. Cool

Edit the bashrc file at /home/username and add this line:

. /home/likegeeks/Desktop/myfuncs

Make sure you type the correct path.

Now the function is available for us to use in the command line directly:

addnum 10 20

use from shell

Note: you may need to log out and log in to use the bash functions from the shell.

Another note: if you make your function name like any of the built-in commands you will overwrite the default command so you should take care of that.

I hope you like the post. Keep coming back.

Thank you.

0

31+ Examples for sed Linux Command in Text Manipulation

In the previous post, we talked about bash functions and how to use them from the command line directly and we saw some other cool stuff. Today we will talk about a very useful tool for string manipulation called sed or sed Linux command. Sed is used to work with text files like log files, configuration files, and other text files. In this post, we are going to focus on sed Linux command which is used for text manipulation, which is a very important step in our bash scripting journey. Linux system provides some tools for text processing, one of those tools is sed. We will discuss the 31+ examples with pictures to show the output of every example.

Continue Reading →

The sed command is an interactive text editor like nano. Sed Linux command edits data based on the rules you provide, you can use it like this:

$ sed options file

You are not limited to use sed to manipulate files, you apply it to the STDIN directly like this:

$ echo "Welcome to LikeGeeks page" | sed 's/page/website/'

sed Linux command

The s command replaces the first text with the second text pattern. In this case, the string “website” was replaced with the word “page”, so the result will be as shown.

The above example was a very basic example to demonstrate the tool. We can use sed Linux command to manipulate files as well.

This is our file:

sed manipulate file

$ sed 's/test/another test' ./myfile

The results are printed to the screen instantaneously, you don’t have to wait for processing the file to the end.

If your file is huge enough, you will see the result before the processing is finished.

Sed Linux command doesn’t update your data. It only sends the changed text to STDOUT. The file still untouched. If you need to overwrite the existing content, you can check our previous post which was talking about redirections.

Using Multiple sed Linux Commands in The Command Line

To run multiple sed commands, you can use the -e option like this:

$ sed -e 's/This/That/; s/test/another test/' ./myfile

sed multiple commands

Sed command must be separated by a semi colon without any spaces.

Also, you can use a single quotation to separate commands like this:

$ sed -e '

> s/This/That/

> s/test/another test/' myfile

sed separate commands

The same result, no big deal.

Reading Commands From a File

You can save your sed commands in a file and use them by specifying the file using -f option.

$ cat mycommands

s/This/That/

s/test/another test/

$ sed -f mycommands myfile

sed read commands from file

Substituting Flags

Look at the following example carefully:

$ cat myfile

$ sed 's/test/another test/' myfile

sed substitute flag

The above result shows the first occurrence in each line is only replaced. To substitute all occurrences of a pattern, use one of the following substitution flags.

The flags are written like this:

s/pattern/replacement/flags

There are four types of substitutions:

g, replace all occurrences.
A number, the occurrence number for the new text that you want to substitute.
p, print the original content.
w file: means write the results to a file.

You can limit your replacement by specifying the occurrence number that should be replaced like this:

$ sed 's/test/another test/2' myfile

sed number flag

As you can see, only the second occurrence on each line was replaced.

The g flag means global, which means a global replacement for all occurrences:

$ sed 's/test/another test/2' myfile

sed global flag

The p flag prints each line contains a pattern match, you can use the -n option to print the modified lines only.

$ cat myfile

$ sed -n 's/test/another test/p' myfile

sed supress lines

The w flag saves the output to a specified file:

$ sed 's/test/another test/w output' myfile

sed send output to file

The output is printed on the screen, but the matching lines are saved to the output file.

Replace Characters

Suppose that you want to search for bash shell and replace it with csh shell in the /etc/passwd file using sed, well, you can do it easily:

$ sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd

Oh!! that looks terrible.

Luckily, there is another way to achieve that. You can use the exclamation mark (!) as string delimiter like this:

$ sed 's!/bin/bash!/bin/csh!' /etc/passwd

Now it’s easier to read.

Limiting sed

Sed command processes your entire file. However, you can limit the sed command to process specific lines, there are two ways:

  • A range of lines.
  • A pattern that matches a specific line.

You can type one number to limit it to a specific line:

$ sed '2s/test/another test/' myfile

sed restricted

Only line two is modified.

What about using a range of lines:

$ sed '2,3s/test/another test/' myfile

sed replace range of lines

Also, we can start from a line to the end of the file:

$ sed '2,$s/test/another test/' myfile

sed replace to the end

Or you can use a pattern like this:

$ sed '/likegeeks/s/bash/csh/' /etc/passwd

sed pattern match

Awesome!!

You can use regular expressions to write this pattern to be more generic and useful.

Delete Lines

To delete lines, the delete (d) flag is your friend.

The delete flag deletes the text from the stream, not the original file.

$ sed '2d' myfile

sed delete line

Here we delete the second line only from myfile.

What about deleting a range of lines?

$ sed '2,3d' myfile

sed delete multiple line

Here we delete a range of lines, the second and the third.

Another type of ranges:

$ sed '3,$d' myfile

sed delete to the end

Here we delete from the third line to the end of the file.

All these examples never modify your original file.

$ sed '/test 1/d' myfile

sed deletepattern match

Here we use a pattern to delete the line if matched on the first line.

If you need to delete a range of lines, you can use two text patterns like this:

$ sed '/second/,/fourth/d' myfile

sed delete range of lines

The first to the third line deleted.

Insert and Append Text

You can insert or append text lines using the following flags:

  • The (i) flag.
  • The  (a) flag.

$ echo "Another test" | sed 'i\First test '

sed insert text

Here the text is added before the specified line.

$ echo "Another test" | sed 'a\First test '

sed append

Here the text is added after the specified line.

Well, what about adding text in the middle?

Easy, look at the following example:

$ sed '2i\This is the inserted line.' myfile

sed insert line

And the appending works the same way, but look at the position of the appended text:

$ sed '2a\This is the appended line.' myfile

sed append line

The same flags are used but with a location of insertion or appending.

Modifying Lines

To modify a specific line, you can use the (c) flag like this:

$ sed '3c\This is a modified line.' myfile

sed modify line

You can use a regular expression pattern and all lines match that pattern will be modified.

$ sed '/This is/c Line updated.' myfile

sed pattern match

Transform Characters

The transform flag (y) works on characters like this:

$ sed 'y/123/567/' myfile

sed transform character

The transformation is applied to all data and cannot be limited to a specific occurrence.

Print Line Numbers

You can print line number using the (=) sign like this:

$ sed '=' myfile

sed line numbers

However, by using -n combined with the equal sign, the sed command displays the line number that contains matching.

$ sed -n '/test/=' myfile

sed hide lines

Read Data From a File

You can use the (r) flag to read data from a file.

You can define a line number or a text pattern for the text that you want to read.

$ cat newfile

$ sed '3r newfile' myfile

sed read data from file

The content is just inserted after the third line as expected.

And this is using a text pattern:

$ sed '/test/r newfile' myfile

sed read match pattern

Cool right?

Useful Examples

We have a file that contains a text with a placeholder and we have another file that contains the data that will be filled in that placeholder.

We will use the (r) and (d) flags to do the job.

The word DATA in that file is a placeholder for a real content which is stored in another file called data.

We will replace it with the actual content:

$ Sed '/DATA>/ {

r newfile

d}' myfile

sed repalce placeholder

Awesome!! as you can see, the placeholder location is filled with the data from the other file.

This is just a very small intro about sed command. Actually, sed Linux command is another world by itself.

The only limitation is your imagination.

I hope you enjoy what’ve introduced today about the string manipulation using sed Linux command.

Thank you.

likegeeks.com

0