shell 函数

传参 $1,$2

变量 local 如果想让变量只在函数内部使用,则使用local 变量名将变量做成局部变量即可

返回值return $?

======================================================

函数的功能

​ 完成特定功能的代码片段(块)

​ 在shell中定义函数可以使用代码模块化,便于复用代码

​ 函数必须先定义才可以使用

1.定义函数

方法1:

​ 函数名(){

​ 函数要实现的功能代码

​ }

方法2:

​ function 函数名 {

​ 函数要实现的功能代码

​ }

函数的调用方法:

​ 函数名称 参数1 参数2

​ 调用函数时可以传递参数,函数中使用$1、$2来传递参数

如果函数在另一个文件中存放,则在使用脚本前先执行该文件source f1.sh

注意:

​ 1.函数接收位置参数:$1 $2 3... 3... 3...n

​ 2.函数接收数组变量: $* 或 $@

​ 3.函数将接收到的所有参数赋给数组 newarray=($@)

​ 4.函数中使用的参数个数 $#

1.1定义一个函数以及去调用

#!/bin/bahs
factorial(){
	factorial=1
	for ((i=1;i<=10;i++))
	do
		factorial=$[$factorial * $i]
	done
	echo "10的阶乘是:$factorial"
}

factorial

解释:第三行:#设置积乘的值为1,因为0的话就乱套了,0乘任何数都得0

第四行:#c语言的风格,定义i=1,当i小于等于10的时候,i的值就加1,先运算,运算完成后,i的值才会加1

第六行:#factorial 变量不是第三行的那个变量而是新定义的变量,变量名不建议重复以及不建议和命令同名,但是在这里变量不会像命令那样去执行,因此可以使用同名的变量名, [ [ [factorial]中的factorial是同一行的变量名作为此变量,例如第一次循环factorial就等于1 12,第二次factorial就是2 23,第三次factorial就是6 64, 第四次factorial就是24 245…依次递增…

1.2使用变量进行函数传参

#!/bin/bash
factorial(){
	factorial=1
	for i in $(seq $num)
	do
		factorial=$[$factorial * $i]
	done
	echo "$num 的阶乘是:$factorial"
}
num=5
factorial

解释:这里定义变量传参,在运行函数前,先定义好传参所用的变量

1.3使用函数位置变量进行传参

function factorial {
	factorial=1
	for ((i=1;i<=$1;i++))
	do
		factorial=$[$factorial * $i]
	done
	echo "$1 的阶乘是:$factorial"
}
factorial 10

解释:这里直接使用函数位置变量,即在执行factorial函数后面加上参数即可传递

第三行:#这里的$1是函数中的位置变量,与shell中的位置变量$1没有任何关系,即使在这里定义$1,执行脚本时./factorial 10也会>报错,因为shell中的位置变量$1不会传参到函数中的$1,如果函数需要传参则在执行函数时在后面加上参数即可,例如factorial 10这样就会被传到函数中

1.4使用shell位置变量向函数位置变量传参

执行方式./factorial 10 20

function factorial {
	factorial=1
	for ((i=1;i<=$1;i++))
	do
		factorial=$[$factorial * $i]
	done
	echo "$1 的阶乘是:$factorial"
}
factorial $1
factorial $2
factorial $3

解释:第九行:#这种函数后面加上shell位置变量就可以在脚本名后面加上参数./factorial 10这样的方法进行执行,这里的$1,$2,$3都会作为函数的第一个位置变量$1传回到函数中

第十行:#虽然这里是$2但是对于函数来说却是第一个参数,就会被传参到函数中的$1位置变量中

第十一行:#虽然这里是$3但是对于函数来说却是第一个参数,就会被传参到函数中的$1位置变量中

2.使用return命令来退出函数并返回特定的退出码

函数既然有位置参数那么也会有返回值,也是$?

函数的返回值是函数最后一条命令执行的结果,非0都是代表函数中最后一条命令执行失败

函数的状态返回码可以自己定义,但是不能超过255,一般利用return来返回函数的状态码

自定义函数状态返回码:return $[2*100]或者直接写一个值,return 3 函数的返回码最高值为255,不能超过255

return后面只能跟一个值,不能跟表达式,而这个值必须是小于等于255的值

2.1return实现函数的返回码

#!/bin/bash
#----------------------利用return实现函数状态返回值---------------------
fun1() {
        read -p "enter number: " number
        return $[2*$number]                     #将运算的值作为状态返回结果
}

fun1
echo "fun2 return value: $?"            #$?的返回值是函数中最后一条命令的返回结果,如果使用了return则返回return的值

2.2return实现函数的返回码—固定值

#!/bin/bash
fun1() {
	echo "return 3"
	return 3
	echo "why"
}
fun1

2.3.如果函数的返回码要求大于255的实现方式

可以使用echo自定义的状态码,然后将函数的输出结果保存到每个变量中

#!/bin/bash
fun2() {
	read -p "enter numbers: " num
	echo $[$num *2]
}
result=$(fun2)
echo "fun2 return value: $result"

3.函数传参位置参数

$1对应函数中的$1,$2对应函数中的$2,$3对应函数中的$3

#!/bin/bash
if [ $# -ne 3 ];then
        echo "usage: $(basename $0) par1 par2 par3"
        exit
fi

fun3() {
        echo $(($1*$2*$3))
}

result=`fun3 $1 $2 $3`

echo "$result"

4.函数传参 数组变量

#!/bin/bash
num=(1 2 3)
num1=(5 2 3)
array() {
        local factorial=1
        for i in $@                     #这里可以使用$@或者$*,使用$*的时候不能加双引号
        do
                factorial=$[$factorial * $i]
        done
        echo "$factorial"
}

array ${num[@]}                 #这里展开就是array 1 2 3所有在函数中可用使用$@或者$*来取所有参数
array ${num1[@]}

5.数组输入,数组输出

#!/bin/bash
num=(10 20 30)
fun(){
	echo "all parmarent: $@"
	local newarray=($@)				
	local i=					
	local outarray=	
	for ((i=0;i<$#;i++))			
	do
		outarray[$i]=$(( ${newarray[$i]} * 5 ))  	
	done
	echo "${outarray[@]}"
}
result=`fun ${num[@]}`
echo "${result[@]}"


array4() {
        echo "all parmaent: $@"
        local newarray1=($@)
        local i=
        local outarray=
        for i in {0..2}                
        do
                outarray1[$i]=$[ ${newarray1[$i]} * 5 ]
        done
        echo "${outarray1[@]}"
}
array4 ${num1[@]}

两者输出一致


解释:
local newarray=($@)				#因为执行函数时是array3 ${num[@]}也就是array3 1 2 3 4,在这里呢使用$@取得所有参数放进newarray中作为新的数组
		
local i=					#将i的值设置为空
		
for ((i=0;i<$#;i++))				#因为普通数组的索引从0开始,因此这里只有四个参数,i=0,i<$#也就是i=0,i<4只取0-3也就满足了元数个数
		
outarray[$i]=$(( ${newarray[$i]} * 5 ))  		 #这里定义了一个outarray的函数,[$i]是索引的名称,${newarray[$i]} * 5是newarray数组中索引名称和outarray>数组中索引名称一致时*5,第一次循环就是outarray[0]=${newarray[0]} * 5,第二次循环就是utarray[1]=${newarray[1]} * 5
		
for i in {0..2}                 #这里不能使用$@因为$@是元数值,如果使用了$@那么在下面i就是10 20 30 因为没有这个索引位所以会报错

7.数组输入,数组输出

跟6的区别在于不再将所有参数保存到新的数组中

#!/bin/bash
num=(10 20 30)
fun() {
	local i=()			
	local j=
	local outarray=
	for i
	do
		outarray[j++]=$[$i*5]
	done
	echo "${outarray[@]}"
}
fun ${num[@]}

解释:local i=()等同于i= 都是表示空

8.创建用户

#!/bin/bash
#-------------批量增删用户
qrxx(){
        if [[ ! $usernumbers =~ ^[0-9]+$ ]];then
                echo -e "\e[31merror parameter\e[0m"
                continue
        fi

        cat <<-EOF
        +---------------------------------------------------------+
                        user information                         
                        userprefix: $userprefix                   
                        userpass: $userpass                       
                        usernumbers: $usernumbers                       
        +---------------------------------------------------------+
        EOF
}
create(){
        echo -en "\e[034mplease enter userprefix userpass usernumbers[ user 123 10 ]: \e[0m"
        read userprefix userpass usernumbers
        qrxx
        echo -en "\e[35mare you sure create user infomation [y|n] \e[0m"
        read action
        case $action in
        y|Y)
                for i in `seq -w $usernumbers`
                do
                        user=$userprefix$i
                        id $user &>/dev/null
                        if [ $? -ne 0 ];then
                                useradd $user
                                echo "$userpass" |passwd --stdin $user &>/dev/null
                                if [ $? -eq 0 ];then
                                        echo "$user is created..."
                                fi
                        else
                                echo "$user already exists..."
                        fi
                done
                ;;
        n|N)
                continue
                ;;
        *)
                echo "error action,please input [y|n]: "
        esac
}

delete(){
        echo -en "\e[034mplease enter userprefix  usernumbers[ user  10 ]: \e[0m"
        read userprefix  usernumbers
        qrxx
        echo -en "\e[35mare you sure delete user information [y|n]: \e[0m"
        read action
        case $action in
        y|Y)
                for i in $(seq -w $usernumbers)
                do
                        user=$userprefix$i
                        id $user &>/dev/null
                        if [ $? -eq 0 ];then
                                userdel -r $user
                                if [ $? -eq 0 ];then
                                        echo "$user is deleted..."
                                fi
                        else
                                echo "$user is not exists... "
                        fi
                done
                ;;
        n|N)
                continue
        esac
}

while :
do
        cat <<-EOF
        +---------------------------------------------------------+
        |                       MENU                              |
        |               1.Batch to create user                    |
        |               2.Batch delete user                       |
        |               q.exit                                    |     
        +---------------------------------------------------------+
        EOF
        echo -en "\e[33mPlease input you want to choose the mode: \e[0m" 
        read mode
        case $mode in
        1)
                create
                ;;
        2)
                delete
                ;;
        q)
                exit
                ;;
        *)
                echo "error"
        esac
done