shell functions and arrays

1 function

1.1 function definition

Popular speaking. Function is to gather a group of relatively independent codes to form a code block, which can complete a specific function.
Essentially, a function is a mapping of a function name to a block of code. After you define a function, you can call its corresponding set of code through the function name.

Advantages of using shell functions:
1. Defining the same program segment as a function can reduce the amount of code in the whole program segment and improve development efficiency.
2. Increase the readability and readability of program segments and improve management efficiency.
3. It can realize the modularization of program function and make the program universal (portability).

1.2 function syntax

function Function name() {
	instructions
	return
	}
	
	Simplified notation 1:
	function Function name {
		instructions
		return
	}

Simplified 2:
Function name ()  {
	instructions
	return
}

1.3 function call

Basic syntax of function call:
function_name param1 param2 ...
function_name represents the name of the function, and param1, param2... Represent the parameters of the function.

Shell uses the same method to handle script parameters and function parameters.
(1) Calling function: directly execute the function name
Function name
(2) Function execution method with parameters:
Function name parameter

Like Shell scripts, users can use location variables in Shell functions to get parameter values.
For example: $0 represents the function script name
$# to get the number of parameters of the function
$1 represents the first parameter
$2 represents the second parameter
$@ system variable, through which users can obtain the values of all parameters
$* system variable, through which users can obtain the values of all parameters.

[root@node1 day6]# vim func.sh
#!/bin/bash
func()
{
  echo "the function has $# parameters"
  echo "all parameters are $*"
  echo "all parameters are $@"
  echo "the scripts's name is $0"
  echo "the first parameter is $1"
}
func hello world
[root@node1 day6]# bash func.sh
the function has 2 parameters
all parameters are hello world
all parameters are hello world
the scripts's name is func.sh
the first parameter is hello

1.4 function return value

Users can use the return statement to return a value, which is the same as most programming languages.
However, in the shell, return can only return integer values between 0 and 255.

In the function, the user writes the data to be returned to stdout. Usually, this operation is completed by echo statement, and then the caller assigns the execution result of the function to a variable

[root@node1 day6]# vim length.sh
#!/bin/bash
{
  str=$1
  return=0
  if [ "$1" != "" ];then
      result=${#str}
  fi  
  echo "$result"
} 
len=$(length "abcd12")
echo "the string's length is $len"

[root@node1 day6]# bash length.sh 
the string's length is 6

1.5 function cases

Example 1: write a script to determine 192.168 0.200-192.168. Which hosts between 0.254 are online.
requirement:
1. Using function to realize the decision process of a host;
2. Call this function in the main program to determine the online status of all hosts within the specified range. Directly using function implementation

Method 1: directly use function implementation (no parameters, no return value)
[root@node1 day6]# vim online_host.sh
#!/bin/bash
online() {
  for i in {200..254};do
     if ping -c 192.168.0.$i &>/dev/null
     then
        echo "192.168.0.$i is up"
     else
        echo "192.168.0.$i is down"
     fi
  done
}

online

[root@node1 day6]# bash online_host.sh 
192.168.0.200 is down
192.168.0.201 is down
192.168.0.202 is down
192.168.0.203 is down

Method 2: use function to pass parameters (with parameters and no return value)
[root@node1 day6]# vim online_host.sh
#!/bin/bash
online() {
   if ping -c 1 $i &>/dev/null
   then
      echo "$1 is up"
   else
      echo "$1 is down"
   fi
}

for i in {200..254}
do
   online 192.168.0.$i
done

Method 3: use the function return value to judge (with parameters and return value)
[root@node1 day6]# vim online_host2.sh
#!/bin/bash
online() {
  if ping -c 1 $1 >&/dev/null
  then
     return 0
  else
     return 1
  fi
}
for i in {200..254}
do
  online 192.168.0.$i
  if [ $? -eq 0 ];then
      echo "192.168.0.$i" is up"
  else
      echo "192.168.0$i" is down"
  fi
done

Example 2: write a script and complete it with a function
1. The function can accept a parameter, which is the user name;
Determine whether a user exists
If it exists, return the shell and UID of the user; And return to the normal state value;
If it does not exist, the user does not exist; And return the error status value;
2, calling function in main program;

[root@node1 day6]# vim user_mess.sh
#!/bin/bash
user() {
  if id $i &>/dev/null
  then
     echo "`grep ^$1 /etc/passwd |  cut -d: -f3,7`"
     return 0
  else
     echo "$1 does not exist"
     return 1
  fi
}

read -p "please input username:" username
until [ "$username" = "quit" -o "$username" = "exit" -o "$username" = "q" ]
do
   user $username
   if [ $? == 0 ];then
      read -p "please input again:" username
   else
      read -p "no $username,please input again:" username
   fi
done
[root@node1 day6]# bash user_mess.sh 
please input username:haha

please input again:root
0:/bin/bash

1.7 recursive function

Functions can call themselves directly or indirectly. In the recursive call of a function, the function is both the caller and the callee.
The calling process of recursive function is to call itself repeatedly, and each call will enter a new layer.

Example: calculate the factorial of the number according to the value entered by the user.

[root@node1 day6]# vim fact.sh
#!/bin/bash
fact()
{
  local n="$1"
  if [ "$n" -eq 0 ]
  then
     result=1
  else
     let "m=n-1"
     fact "$m"
     let "result=$n * $?"
  fi
  return $result
}
fact "$1"
echo "Factorial of $1 is $?"
[root@node1 day6]# bash fact.sh 0
Factorial of 0 is 1
[root@node1 day6]# bash fact.sh 5
Factorial of 5 is 120

Note: by default, all variables except the special variables associated with function parameters have a global valid range. In addition, in the function, if the local keyword is not used for modification, the variables in the function are also global variables.

Example 1: the variable of the function is a global variable

[root@node1 day6]# vim global.sh
#!/bin/bash
var="hello world"
func()
{
  var="orange"
  echo $var
  var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"

[root@node1 day6]# bash global.sh 
hello world
orange
orange
hello

Example 2: the variable of the function is specified as a local variable using local

[root@node1 day6]# vim 7.sh
#!/bin/bash
var="hello world"
func()
{
  local var="orange"
  echo "$var"
  local var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"
[root@node1 day6]# bash 7.sh 
hello world
orange
hello world

2 array

A data type that organizes several variables of the same type in a certain order

2.1 defining arrays

Method 1: enclose the variable value with parentheses and assign it to the array variable. Each variable should be separated by a space.

array=(value1 value2 value3 ... )

Method 2: enclose the variable value with parentheses, and assign value in the form of key value pair.

array=([0]=one [1]=two [2]=three ... [n]=valuen)

Method 3: define the values of array variables respectively

array[0]=a;array[1]=b;array[2]=c

Method 4: dynamically define variables and use the output result of the command as the content of the array.

array=(command)

Method 5: define the array through declare statement

declare -a array

Define associative arrays: associative arrays use strings as subscripts, not integers, so that you can see the meaning of the name. Unlike normal arrays, associative arrays must be created using the declare command with the - A option

Method 1: assign one value at a time
[root@node1 day6]# declare -A array
[root@node1 day6]# array[shuju1]=apple
[root@node1 day6]# array[shuju2]=banana
[root@node1 day6]# echo ${array[*]}
banana apple
 Method 2: assign multiple values at a time
[root@node1 day6]# declare -A a
[root@node1 day6]# a=([index1]=tom [index2]=jack [index3]=alice)
[root@node1 day6]# echo ${a[@]}
tom jack alice

2.2 array operation

Get all elements:
[root@node1 day6]# echo ${array[*]}
banana apple
 Get element subscript:
[root@node1 day6]# echo ${!array[@]}
shuju2 shuju1
[root@node1 day6]# echo ${!array[*]}
shuju2 shuju1
 Get array length:
[root@node1 day6]# echo ${#array[*]}
2
[root@node1 day6]# echo ${#array[@]}
2
 Get the first element:
[root@node1 day6]# echo ${array[0]}
Add element:
[root@node1 day6]# array[3]=d
 Add multiple elements:
[root@node1 day6]# array+=(e f g)
Delete the first element:
[root@node1 day6]# unset array[0]
Delete array:
[root@node1 day6]# unset array

Traversal array:

Method 1:
[root@node1 day6]# vim bianli.sh
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for ((i=0;i<${#IP[*]};i++)); do
echo ${IP[$i]}
done
[root@node1 day6]# bash bianli.sh 
192.168.1.1
192.168.1.2
192.168.1.3

Method 2:
[root@node1 day6]# vim bianli1.sh
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for IP in ${IP[*]}; do
echo $IP
done
[root@node1 day6]# bash bianli1.sh 
192.168.1.1
192.168.1.2
192.168.1.3:

2.3 array cases

1. Read the string n times from "standard input", and the string input each time is saved in the array array

[root@node1 day6]# vim str.sh
#!/bin/bash
i=0
n=5
while [ "$i" -lt $n ];do
   echo "please input strings... `expr $i + 1`"
   read array[$i]
   b=${array[$i]}
   echo "$b"
   i=`expr $i + 1`
done
[root@node1 day6]# bash str.sh 
please input strings... 1
a
a
please input strings... 2
fa
fa
please input strings... 3
fa
fa
please input strings... 4
few
few
please input strings... 5
dwdkdnwkff
dwdkdnwkff

2. Put the letters in the string into the array one by one and output to "standard output"

[root@node1 day6]# vim letter.sh
#!/bin/bash
chars='ajfsdjkfwekefw'
for ((i=0;i<${#chars};i++));do
   array[$i]=${chars:$i:1}
   echo ${array[$I]}
done

explain: ${chars:$i:1},Indicates from chars String $i Start at position, get 1 character

3. Save the three numbers 1-3 in the array, multiply them by 8, and then output them in turn.

[root@node1 day6]# vim number.sh
#!/bin/bash
array=(`seq 3`)
for ((i=0;i<${#array[@]};i++))
do
   echo $[${array[$i]}*8]
done
[root@node1 day6]# bash number.sh 
8
16
24

Keywords: Linux shell

Added by knford on Sat, 18 Dec 2021 17:58:35 +0200