SHELL编程

发布于:2025-06-13 ⋅ 阅读:(16) ⋅ 点赞:(0)

一.循环控制

1.exit

exit在shell中是一个特殊的程序退出信号,不仅仅可以直接退出当前程序,还可以设定退出后的状态返回值,使用方式如下:
		exit num


注意:
	1 在脚本中遇到exit命令,脚本立即终止;终止退出状态取决于exit命令后面的数字
	2 如果exit后面无数字,终止退出状态取决于exit命令前面命令执行结果

实践1- 设定退出状态值

网段内主机地址的存活性探测
[root@192 ~]# ping -c1 -W1 10.0.0.12 &> /dev/null && echo '10.0.0.12 is up' || (echo '10.0.0.12 is unreachable'; exit 1)
10.0.0.12 is up
[root@192 ~]# ping -c1 -W1 10.0.0.13 &> /dev/null && echo '10.0.0.13 is up' || (echo '10.0.0.13 is unreachable'; exit 6)
10.0.0.13 is unreachable
[root@192 ~]# echo $?
6

服务器网址探测
[root@192 ~]# curl -s -o /dev/null baidu.com &> /dev/null && echo 'baidu.com is up' || (echo 'baidu.com is unreachable'; exit 7)
baidu.com is up
[root@192 ~]# curl -s -o /dev/null baidu.com1 &> /dev/null && echo 'baidu.com1 is up' || (echo 'baidu.com1 is unreachable'; exit 7)
baidu.com1 is unreachable
[root@192 ~]# echo $?
7

实践2-嵌套循环中exit退出程序

查看脚本内容
[root@localhost ~]# cat exit_multi_for.sh
#!/bin/bash
# 功能:exit退出脚本程序

# 外层循环遍历1-5
for var1 in {1..5}
do
   # 内层循环遍历a-d
   for var2 in {a..d}
   do
      # 判断退出条件,var1是2或者var2是c就退出内层循环
      if [ $var1 -eq 2 -o "$var2" == "c" ]
      then
         exit 111
      else
         echo "$var1 $var2"
      fi
   done
done



脚本执行效果
[root@192 ~]# /bin/bash exit_multi_for.sh
1 a
1 b
[root@192 ~]# echo $?
111
结果显示:
	一旦匹配到任何一个信息,就直接退出程序,而且状态码还是我们定制的。

2.break

    break命令是在处理过程中终止循环的一种简单方法。可以使用break命令退出任何类型的循环,包括for、while、until等。

break主要有两种场景的表现样式:
	单循环场景下,break是终止循环
		- 仅有一层 while 、for、until等
	嵌套循环场景下,break是可以终止内层循环和外层循环。
		- 存在多层while、for、until嵌套等

语法格式

break语法格式:
	for 循环列表
	do
	    ...
	    break num
	done
	注意:
		单循环下,break就代表退出循环
		多循环下,break的num大于嵌套的层数,就代表退出循环

实践1-break终止单层循环

查看脚本内容
[root@localhost ~]# cat break_single_while.sh
#!/bin/bash
# 功能:break退出单层循环
while true
do
    read -p "输入你的数字,最好在 1 ~ 5: " aNum
    case $aNum in
        1|2|3|4|5)
          echo "你的数字是 $aNum!"
        ;;
        *)
          echo "你选择的数字没在 1 ~ 5, 退出!"
          break
        ;;
    esac
done




[root@localhost ~]# /bin/bash break_single_while.sh
输入你的数字,最好在 1 ~ 5: 2
你的数字是 2!
输入你的数字,最好在 1 ~ 5: 5
你的数字是 5!
输入你的数字,最好在 1 ~ 5: 6
你选择的数字没在 1 ~ 5, 退出!

结果显示:
	一旦出发break,当前循环就终止了

实践2-多层循环下break退出内层循环

[root@localhost ~]# cat break_multi_in_while.sh
#!/bin/bash
# 功能:break退出内层循环

# 外层循环遍历1-5
for var1 in {1..5}
do
   # 内层循环遍历a-d
   for var2 in {a..d}
   do
      # 判断退出条件,var1是2或者var2是c就退出内层循环
      if [ $var1 -eq 2 -o "$var2" == "c" ]
      then
         break
      else
         echo "$var1 $var2"
      fi
   done
done




脚本执行效果
[root@localhost ~]# /bin/bash break_multi_in_while.sh
1 a
1 b
3 a
3 b
4 a
4 b
5 a
5 b
结果显示:
	一旦出发break,则匹配内容及其后面的信息就不再输出了

实践3-多层循环下break退出外层循环

[root@localhost ~]# cat break_multi_out_while.sh
#!/bin/bash
# 功能:break退出外层循环

# 外层循环遍历1-5
for var1 in {1..5}
do
   # 内层循环遍历a-d
   for var2 in {a..d}
   do
      # 判断退出条件,var1是2或者var2是c就退出内层循环
      if [ $var1 -eq 2 -o "$var2" == "c" ]
      then
         break 2
      else
         echo "$var1 $var2"
      fi
   done
done




脚本执行效果
[root@localhost ~]# /bin/bash break_multi_out_while.sh
1 a
1 b
结果显示:
	一旦匹配内层,则直接终止外层的循环

3.continue

continue命令是在处理过程中跳出循环的一种简单方法。可以使用continue命令跳出当前的循环直接进入到下一个循环,包括for、while、until等。

continue主要有两种场景的表现样式:
	单循环场景下,continue是跳出当前循环
		- 仅有一层 while 、for、until等
	嵌套循环场景下,continue是可以跳出内层循环和外层循环。
		- 存在多层while、for、until嵌套等

语法格式

continue语法格式:
	for 循环列表
	do
	    ...
	    continue num
	done
	注意:
		单循环下,continue就代表跳出当前循环
		多循环下,continue的num就代表要继续的循环级别

实践1-continue跳出当前单层循环

查看脚本内容
[root@localhost ~]# cat continue_single_while.sh
#!/bin/bash
# 功能:continue退出单层循环
while true
do
    read -p "输入你的数字,最好在 1 ~ 5: " aNum
    case $aNum in
        1|2|3|4|5)
          echo "你的数字是 $aNum!"
        ;;
        *)
          echo "你选择的数字没在 1 ~ 5, 退出!"
          continue
        ;;
    esac
done



[root@localhost ~]# /bin/bash continue_single_while.sh
输入你的数字,最好在 1 ~ 5: 2
你的数字是 2!
输入你的数字,最好在 1 ~ 5: 6
你选择的数字没在 1 ~ 5, 退出!
输入你的数字,最好在 1 ~ 5: 1
你的数字是 1!
输入你的数字,最好在 1 ~ 5: ^C

结果显示:
	即使输出的数据不是我们想要的,也不会退出循环逻辑

实践2-多层循环下continue退出内层循环

[root@localhost ~]# cat continue_multi_in_while.sh
#!/bin/bash
# 功能:continue退出内层循环

# 外层循环遍历1-5
for var1 in {1..5}
do
   # 内层循环遍历a-d
   for var2 in {a..d}
   do
      # 判断退出条件,var1是2或者var2是c就退出内层循环
      if [ $var1 -eq 2 -o "$var2" == "c" ]
      then
         continue
      else
         echo "$var1 $var2"
      fi
   done
done


脚本执行效果
[root@localhost ~]# /bin/bash break_multi_in_while.sh
1 a
1 b
1 d
3 a
3 b
3 d
4 a
4 b
4 d
5 a
5 b
5 d

结果显示:
	满足条件的信息,都直接跳到下一循环,继续执行,可以看到内层的d信息输出了

实践3-多层循环下continue退出外层循环

[root@localhost ~]# cat continue_multi_out_while.sh
#!/bin/bash
# 功能:continue退出外层循环

# 外层循环遍历1-5
for var1 in {1..5}
do
   # 内层循环遍历a-d
   for var2 in {a..d}
   do
      # 判断退出条件,var1是2或者var2是c就退出内层循环
      if [ $var1 -eq 2 -o "$var2" == "c" ]
      then
         continue 2
      else
         echo "$var1 $var2"
      fi
   done
done


脚本执行效果
[root@localhost ~]# /bin/bash continue_multi_out_while.sh
1 a
1 b
3 a
3 b
4 a
4 b
5 a
5 b
结果显示:
	满足条件的信息,直接将外层循环跳到下一循环,继续执行,可以看到外层的3-5信息输出了

4.shift

shift是一个特殊的循环控制命令,它的特点主要是依次从输入信息列表中获取相关的参数数据值,然后走循环。

语法格式

shift语法格式:
	for 循环列表
	do
	    ...
	    shift
	done
	注意:
		shift 从用户输入的信息中提取第一个位置的数据内容,每走一个循环,从下一个位置获取输入参数

实践1-依次获取所有参数的内容

查看脚本效果
[root@localhost ~]# cat shift_get_args.sh
#!/bin/bash
#功能:shift依次从输入的参数列表中获取内容

# 定制一套循环逻辑,直到参数位置内容为空
until [ -z "$1" ] 
do
   echo "脚本的第1个位置参数内容是: $1, 当前脚本参数数量: $#"
   # 接收完第一个参数后,直接将起始值移至下一个位置
   shift
done



脚本执行效果
[root@localhost ~]# /bin/bash shift_get_args.sh aa bb cc dd ee
脚本的第1个位置参数内容是: aa, 当前脚本参数数量: 5
脚本的第1个位置参数内容是: bb, 当前脚本参数数量: 4
脚本的第1个位置参数内容是: cc, 当前脚本参数数量: 3
脚本的第1个位置参数内容是: dd, 当前脚本参数数量: 2
脚本的第1个位置参数内容是: ee, 当前脚本参数数量: 1
结果显示:
	每次从脚本的第一个位置获取的内容在逐渐变化中。

实践2-创建指定的系统用户

查看脚本效果
[root@localhost ~]# cat shift_add_user.sh
#!/bin/bash
# 功能:shift批量创建指定的用户

# 定制批量创建用户的业务逻辑
if [ $# -ne 0 ]
then
    # 注意: 这里用的是 -n,后面的$1两侧要有"",如果用until语句的话使用 -z表达式
    while [ -n "$1" ]
    do
        # 创建用户
        useradd $1
        echo -e "\e[31m用户 $1 创建成功\e[0m"
        # 移动输入参数
        shift
    done
else
    echo -e "\e[31mUsage: /bin/bash $0 arg_list\e[0m"
fi


查看脚本执行效果
[root@localhost ~]# /bin/bash shift_add_user.sh
Usage: /bin/bash shift_add_user.sh arg_list
[root@localhost ~]# /bin/bash shift_add_user.sh zhangsan lisi wangwu zhaoliu
用户 zhangsan 创建成功
用户 lisi 创建成功
用户 wangwu 创建成功
用户 zhaoliu 创建成功
[root@localhost ~]# cat /tmp/user.txt
用户: zhangsan, 密码: 4m4njspn
用户: lisi, 密码: sFEFcecC
用户: wangwu, 密码: rsDmtkcQ
用户: zhaoliu, 密码: Ehsj2fZo

二.函数基础

1.函数

    所谓的函数,本质上就是一段能够满足特定功能的代码块。一旦定义好函数代码后,我们就可以在脚本的很多位置随意的使用。
    定义功能代码块的动作叫 函数定义,使用函数代码的动作叫 函数调用。

函数的优势:
    1. 代码模块化,调用方便,节省内存
    2. 代码模块化,代码量少,排错简单
    3. 代码模块化,可以改变代码的执行顺序

基本语法

定义函数:
	样式1:标准格式
    function 函数名{		
        函数体				
    }						
	样式2:简约格式
    函数名() {		
        函数体				
    }
注意:
	function 的作用和 () 的作用是一样的,都是定义一个函数。
	函数的名称是自定义的,而且在脚本范围内必须唯一。
	函数体内是普通的能够正常执行的命令,命令的执行流程符合顺序逻辑。

实践1-标准函数的实践

[root@localhost ~]# cat function_simple_test.sh
#!/bin/bash
# 功能:简单函数的定义和调用

# 定制一个函数,提示脚本的使用方式
function Usage {
    echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}

# 定制脚本使用逻辑
if [ $# -eq 1 ]
then
    echo "您输入的脚本参数是1个"
else
    Usage
fi

脚本执行效果
[root@localhost ~]# /bin/bash function_simple_test.sh
脚本的使用帮助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test.sh aa
您输入的脚本参数是1个
[root@localhost ~]# /bin/bash function_simple_test.sh aa bb
脚本的使用帮助信息: xxx

实践2-变种函数的实践

[root@localhost ~]# cat function_simple_test2.sh
#!/bin/bash
# 功能:简单函数的定义和调用

# 定制一个函数,提示脚本的使用方式
Usage() {
    echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}

# 定制脚本使用逻辑
if [ $# -eq 1 ]
then
    echo "您输入的脚本参数是1个"
else
    Usage
fi



脚本执行效果
[root@localhost ~]# /bin/bash function_simple_test2.sh
脚本的使用帮助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test2.sh aa
您输入的脚本参数是1个
[root@localhost ~]# /bin/bash function_simple_test2.sh aa bb
脚本的使用帮助信息: xxx

实践3-函数的调用顺序和名称唯一 实践

[root@localhost ~]# cat function_simple_test3.sh
#!/bin/bash
# 功能:简单函数的定义和调用

# 定制一个函数,提示脚本的使用方式
Usage() {
    echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}
echo "第一次调用效果: "
Usage

# 定制同名的函数,提示脚本的使用方式
Usage() {
    echo -e "\e[31m脚本的使用帮助信息-------: xxx\e[0m"
}
# 定制脚本使用逻辑
if [ $# -eq 1 ]
then
    # 调用一个后面才会生成的函数
    func
else
    Usage
fi

# 定制一个函数
func() {
    echo "您输入的脚本参数是1个"
}


脚本执行效果
[root@localhost ~]# /bin/bash function_simple_test3.sh
第一次调用效果:
脚本的使用帮助信息: xxx
脚本的使用帮助信息-------: xxx
[root@localhost ~]# /bin/bash function_simple_test3.sh a
第一次调用效果:
脚本的使用帮助信息: xxx
function_simple_test3.sh:行18: func: 未找到命令

结果显示:
	函数名称重复的话,会导致同名函数被覆盖
	函数在没有定义前调用的话,会导致异常报错

2.函数退出

    我们可以将函数代码块,看成shell脚本内部的小型脚本,所以说函数代码块也会有执行状态返回值。对于函数来说,它通常支持两种种状态返回值的样式。

样式1-默认的退出状态
	默认情况下,函数的退出状态是函数体内的最后一条命令的退出状态,可以通过 $? 来获取
样式2-return定制状态返回值
	在函数体内部,通过return定制状态返回值的内容
	注意:
		return的状态返回值必须尽快使用,否则会被其他return的值覆盖
		return的状态返回值必须在 0-255,否则失效

实践1-默认退出状态

[root@localhost ~]# cat function_exit_status1.sh
#!/bin/bash
# 功能:函数默认状态返回值

# 定制成功运行的函数
ok_func() {
    echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}
# 定制一个运行失败的函数
err_func() {
    666666
}
# 定制脚本使用逻辑
if [ $# -eq 1 ]
then
    err_func
    echo "错误函数的执行状态返回值: " $?
else
    ok_func
    echo "成功函数的执行状态返回值: " $?
fi


脚本执行效果
[root@localhost ~]# /bin/bash function_exit_status1.sh
脚本的使用帮助信息: xxx
成功函数的执行状态返回值:  0
[root@localhost ~]# /bin/bash function_exit_status1.sh aa
function_exit_status1.sh:行10: 666666: 未找到命令
错误函数的执行状态返回值:  127
[root@localhost ~]# lll; echo $?
bash: lll: 未找到命令
127
结果显示:
	对于异常的函数来说,默认的状态返回值有安全隐患

实践2-return定制函数的返回值实践

[root@localhost ~]# cat function_exit_status2.sh
#!/bin/bash
# 功能:return定制函数状态返回值

# 定制成功运行的函数
ok_func() {
    echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
    # 定制超范围的状态返回值
    return 666
}
# 定制一个运行失败的函数
err_func() {
    666666
    # 定制状态返回值
    return 222
}
# 定制脚本使用逻辑
if [ $# -eq 1 ]
then
    err_func
    echo "错误函数的执行状态返回值: " $?
else
    ok_func
    echo "成功函数的执行状态返回值: " $?
fi

脚本执行效果
[root@localhost ~]# /bin/bash function_exit_status2.sh
脚本的使用帮助信息: xxx
成功函数的执行状态返回值:  154
[root@localhost ~]# /bin/bash function_exit_status2.sh aa
function_exit_status2.sh:行12: 666666: 未找到命令
错误函数的执行状态返回值:  222
结果显示:
	return的状态返回值范围必须满足要求

3.传参函数

简单的函数定义和调用的实践,我们只能实现固定内容的输出,不具有灵活性。其实函数作为shell脚本内部的小脚本也支持脚本传参的一系列能力。基本语法效果如下

定义函数:
    函数名() {		
        函数体	${变量名}			
    }
注意:
	函数体内通过 ${变量名} 来实现函数体的功能通用性。


调用函数:			
	函数名 参数			
注意:
	函数在调用的时候,接收一些参数并传输到函数体内部。

实践1-传参函数实践

查看脚本内容
[root@localhost ~]# cat function_arg_input.sh
#!/bin/bash
# 功能:传参函数定义和调用

# 定制数据运算的函数
add_func() {
    echo $(( $1 + $2 ))
}
sub_func() {
    echo $(( $1 - $2 ))
}
mul_func() {
    echo $(( $1 * $2 ))
}
div_func() {
    echo $(( $1 / $2 ))
}

echo -n "4+3="; add_func 4 3
echo -n "4-3="; sub_func 4 3
echo -n "4*3="; mul_func 4 3
echo -n "4/3="; div_func 4 3



脚本执行效果
[root@localhost ~]# /bin/bash function_arg_input.sh
4+3=7
4-3=1
4*3=12
4/3=1

4.脚本传参

传参函数定义和调用的实践,实现了函数层面的灵活性,但是它受到函数调用本身的参数限制。往往这些参数我们需要在脚本执行的时候传递进去,从而实现脚本功能的灵活性。
	基本语法效果如下

定义函数:
    函数名() {		
        函数体	${函数参数}			
    }
    
调用函数:
	函数名	${脚本参数}

脚本执行:
	/bin/bash /path/to/scripts.sh arg
	
注意:
	由于脚本内部调用脚本参数和函数体内调用函数参数都遵循位置变量的使用
	所以,一般情况下,我们会借助于临时变量的方式接收各自的参数,从而避免引起误会

实践1-脚本传参函数实践

查看脚本内容
[root@localhost ~]# cat function_arg_scripts.sh
#!/bin/bash
# 功能:脚本传参函数调用

# 定制数据运算的函数
add_func() {
    echo $(( $1 + $2 ))
}
sub_func() {
    echo $(( $1 - $2 ))
}
mul_func() {
    echo $(( $1 * $2 ))
}
div_func() {
    echo $(( $1 / $2 ))
}

[ $# -ne 2  ] && echo "必须传递两个数字参数" && exit
echo -n "$1+$2="; add_func $1 $2
echo -n "$1-$2="; sub_func $1 $2
echo -n "$1*$2="; mul_func $1 $2
echo -n "$1/$2="; div_func $1 $2

注意:
	这种简单的脚本传参函数调用,导致大量的位置参数,容易引起混乱,需要改造


脚本执行效果
[root@localhost ~]# /bin/bash function_arg_scripts.sh
必须传递两个数字参数
[root@localhost ~]# /bin/bash function_arg_scripts.sh 5 4
5+4=9
5-4=1
5*4=20
5/4=1

实践2-脚本传参函数进阶实践

查看脚本内容
[root@localhost ~]# cat function_arg_scripts2.sh
#!/bin/bash
# 功能:传参函数定义和调用

# 接收脚本传参
arg1=$1
arg2=$2
# 定制数据运算的函数
add_func() {
    num1=$1
    num2=$2
    echo $(( ${num1} + ${num2} ))
}
sub_func() {
    num1=$1
    num2=$2
    echo $(( ${num1} - ${num2} ))
}
mul_func() {
    num1=$1
    num2=$2
    echo $(( ${num1} * ${num2} ))
}
div_func() {
    num1=$1
    num2=$2
    echo $(( ${num1} / ${num2} ))
}

[ $# -ne 2  ] && echo "必须传递两个数字参数" && exit
echo -n "${arg1}+${arg2}="; add_func ${arg1} ${arg2}
echo -n "${arg1}-${arg2}="; sub_func ${arg1} ${arg2}
echo -n "${arg1}*${arg2}="; mul_func ${arg1} ${arg2}
echo -n "${arg1}/${arg2}="; div_func ${arg1} ${arg2}



脚本执行效果
[root@localhost ~]# /bin/bash function_arg_scripts2.sh
必须传递两个数字参数
[root@localhost ~]# /bin/bash function_arg_scripts2.sh 7 5
7+5=12
7-5=2
7*5=35
7/5=1

5.函数变量

在函数作用范围中,我们可以通过大量的变量来实现特定数据的临时存储,不仅仅可以实现脚本层面的变量可视化,还可以借助于变量本身的全局和本地的特点实现更加强大的功能场景。

1.全局变量:
    默认情况下,脚本中的普通变量就是全局变量,作用范围是shell脚本的所有地方,在函数内部也可以正常使用 而且函数内可以可以修改脚本级别的全局变量
2.局部变量:
    我们可以通过local语法,将变量的作用范围限制在一段代码块范围中。
    注意:脚本内无法使用local语法,仅限于函数体内

实践1-全局变量实践
查看脚本内容
[root@localhost ~]# cat function_env_test.sh
#!/bin/bash
# 功能:全局变量实践

# 定制普通的全局变量
message="helloworld"

# 定制一个函数,提示脚本的使用方式
function Usage {
    echo "直接调用脚本的message: ${message}"
    message="function-message"
    echo "函数体重置后的message: ${message}"
}

# 定制脚本使用逻辑
while true
do
    read -p "查看变量的方式[ 1-脚本内 | 2-函数内 ]:" type
    if [ ${type} == "1" ];then
        # 直接在脚本环境使用全局变量
        echo ${message}
    elif [ ${type} == "2" ];then
        # 函数内部使用全局变量
        Usage
    fi
done


脚本执行效果
[root@localhost ~]# /bin/bash function_env_test.sh
查看变量的方式[ 1-脚本内 | 2-函数内 ]:1
helloworld
查看变量的方式[ 1-脚本内 | 2-函数内 ]:2
直接调用脚本的message: helloworld
函数体重置后的message: function-message
查看变量的方式[ 1-脚本内 | 2-函数内 ]:1
function-message						# 结果显示,函数体内的变量生效了
查看变量的方式[ 1-脚本内 | 2-函数内 ]:^C
[root@localhost ~]#
结果显示:
	对于脚本的普通变量,函数内外都可以正常使用,而且函数内可以直接修改脚本级别的普通变量

实践2-本地变量实践

查看脚本内容
[root@localhost ~]# cat function_env_test2.sh
#!/bin/bash
# 功能:local定制函数级别的局部变量实践

# 定制普通变量
message="helloworld"
local local_env="local"

# 定制一个函数,提示脚本的使用方式
function Usage {
    echo "直接调用脚本的变量: ${message}-${local_env}"
    local message="function-message"
    echo "函数体重置后的变量: ${message}-${local_env}"
}

# 定制脚本使用逻辑
while true
do
    read -p "查看变量的方式[ 1-脚本内 | 2-函数内 ]:" type
    if [ ${type} == "1" ];then
        # 直接在脚本环境使用普通变量
        echo ${message}
    elif [ ${type} == "2" ];then
        # 函数内部使用普通变量
        Usage
    fi
done


脚本执行效果
[root@localhost ~]# /bin/bash function_env_test2.sh
function_env_test2.sh: 第 6 行:local: 只能在函数中使用
查看变量的方式[ 1-脚本内 | 2-函数内 ]:1
helloworld
查看变量的方式[ 1-脚本内 | 2-函数内 ]:2
直接调用脚本的变量: helloworld-
函数体重置后的变量: function-message-
查看变量的方式[ 1-脚本内 | 2-函数内 ]:1
helloworld
查看变量的方式[ 1-脚本内 | 2-函数内 ]:^C
[root@localhost ~]#
结果显示:
	local仅限于函数中使用,函数外部无法使用
	经过local限制后的环境变量,无法被函数体外进行使用

6.数组传递

我们知道在shell脚本中,数组可以帮助我们做很多灵活的事情,尤其是数据的归类存储。而数组在函数的使用过程中,还是受到了一定程度的限制。这些限制主要体现在以下几个方面;

限制1:
	以变量的方式传递数组给函数,函数内部无法正常使用
限制2:
	我们只能先解析所有数组元素,然后再传递给函数,接着在函数体内部重新组合
限制3:
	函数内部以echo方式输出数组所有元素,然后再函数外部重新组合为数组

实践1-函数无法正常接收数据元素

查看脚本内容
[root@localhost ~]# cat function_array_input.sh
#!/bin/bash
# 功能: 函数接收数组元素

# 定制功能函数
func_array(){
    echo "函数内接收的参数: $@"
}

# 定制数组变量
myarray=(aa bb cc dd ee)
echo "myarray数组的所有元素有: ${myarray[@]}"

# 数组传递给函数
func_array $myarray

脚本执行效果
[root@localhost ~]# /bin/bash function_array_input.sh
myarray数组的所有元素有: aa bb cc dd ee
函数内接收的参数: aa

结果显示:
	虽然我们传递数组给函数,但是函数无法正常接收数组

实践2-函数接收数组

查看脚本内容
[root@localhost ~]# cat function_array_input2.sh
#!/bin/bash
# 功能: 函数接收数组元素

# 定制功能函数
func_array(){
    echo "函数内接收的参数: $@"
    func_arr=($(echo $@))
    echo "函数内func_arr的数组元素有: ${func_arr[@]}"
}

# 定制数组变量
myarray=(aa bb cc dd ee)
echo "myarray数组的所有元素有: ${myarray[@]}"

# 数组解析后,将所有元素传递给函数
func_array ${myarray[@]}


脚本执行效果
[root@localhost ~]# /bin/bash function_array_input2.sh
myarray数组的所有元素有: aa bb cc dd ee
函数内接收的参数: aa bb cc dd ee
函数内func_arr的数组元素有: aa bb cc dd ee

实践3-脚本接收函数内数组

查看脚本内容
[root@localhost ~]# cat function_array_output.sh
#!/bin/bash
# 功能: 脚本接收函数内数组元素

# 定制功能函数
func_array(){
    # 函数体内构造新数组
    func_arr=($(echo $@))
    # 生成新数组
    for (( i=0; i<${#func_arr[@]}; i++ ))
    do
        newarray[$i]=$[ ${func_arr[$i]} * 3 ]
    done
    # 逐个返回数组元素
    echo ${newarray[@]}
}

# 定制数组变量
myarray=(1 2 3 4 5)
echo "myarray数组的所有元素有: ${myarray[@]}"

# 接收函数体返回的数组内容
result=($(func_array ${myarray[@]}))
echo "函数返回的result数组元素:${result[@]}"


脚本执行效果
[root@localhost ~]# /bin/bash function_array_output.sh
myarray数组的所有元素有: 1 2 3 4 5
函数返回的result数组元素:3 6 9 12 15