Shell 脚本之函数及数组

文章目录

  • 1 函数
    • 1.1 函数的作用
    • 1.2 函数的基本格式
    • 1.2 函数注意事项
    • 1.3 获取函数返回值
    • 1.4 函数传参
    • 1.5 函数变量的作用范围
    • 1.6 递归(函数调用自己本身的函数)
      • 1.6.1 递归阶乘
      • 1.6.2 递归目录
    • 1.7 函数库
  • 2 数组
    • 2.1 shell数组的定义
    • 2.2 定义和获取数组
    • 2.3 获取数组的长度及获取某一个元素的值
    • 2.4 判断数组是否完整
    • 2.5 数组遍历
    • 2.6 数组分片、截取
    • 2.7 数组字符替换
    • 2.8 删除数组和追加数组元素
    • 2.9 向函数传数组参数

1 函数

使用函数可以避免代码重复;使用函数可以将大的工程分割为若干小的功能模块,代码的可读性更强

1.1 函数的作用

  • 语句块定义成函数约等于别名,定义函数,再引用函数
  • 封装的可重复利用的具有特定功能的代码

1.2 函数的基本格式

方法一
function 函数名 { 
   命令序列
	[return x]         #使用return或者exit可以显式的结束函数
}

方法二
函数名(){
    命令序列
}

函数的调用:可以在脚本的任何位置定义,但必须在函数后调用(先定义在调用)
######### main ##########
可以在主代码区域中直接使用函数名调用函数

例如

#!/bin/bash 
#文件上方先定义函数,然后在主代码部分调用函数
function test1 {

  read -p "请输入一个整数:" num   #通过键盘输入为变量num赋值
  echo $[num * 2]    #输出变量num的值乘2的值
#使用return要注意,有范围
}

############## main #############
result=$(test1)  #调用函数,直接获取函数test1的结果
echo $result    #再运行echo $result

Shell 脚本之函数及数组_第1张图片

1.2 函数注意事项

  • 直接写函数中调用
  • 函数直接写函数名同名函数后一个生效
  • 调用函数一定要先定义
  • 只要先定义了调用的其他函数定义顺序无关

1.3 获取函数返回值

方法一
return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
使用原则:
1、函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
2、退出状态码必须是0~255,超出时值将为除以256取余

方法二
在函数体中用echo输出,并在函数体外使用变量赋值后,可再进一步对函数的返回值操作

1.4 函数传参

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…即使用位置参数来实现参数传递。

例1:

[root@localhost hanshu]# vim hanshu2.sh

#!/bin/bash
sum1 () {
  sum=$[$1 + $2]
  echo $sum
}
########### main ##########
read -p "请输入第一个位置参数:" first
read -p "请输入第二个位置参数:" second
sum1 $first $second

Shell 脚本之函数及数组_第2张图片
例2:

#!/bin/bash
sum2 () {
 #函数中的 $1 $2 代表调用函数时,函数后面跟的位置参数
  echo $1
  echo $2
}
########### main ##########
#主体代码中的 $1 $2 代表执行脚本时,脚本后面跟的位置参数
sum2 $2 $1

Shell 脚本之函数及数组_第3张图片
Shell 脚本之函数及数组_第4张图片

1.5 函数变量的作用范围

  • 函数在Shell脚本中仅在当前shell环境中有效
  • Shell脚本中变量默认全局有效
  • 将变量限定在函数内部使用local命令

例1:全局有效
Shell 脚本之函数及数组_第5张图片
Shell 脚本之函数及数组_第6张图片
例2:函数内部使用
Shell 脚本之函数及数组_第7张图片
Shell 脚本之函数及数组_第8张图片

1.6 递归(函数调用自己本身的函数)

1.6.1 递归阶乘

[root@localhost hanshu]# vim hanshu6.sh

#!/bin/bash
#使用递归计算阶乘
fact() {
  if [ $1 -eq 1 ];then
    echo 1
  else
    local temp=$[$1 - 1]
    local result=$(fact $temp)
    echo $[$1 * $result]
  fi
}
########## main #########
read -p "请输入一个正整数:" num
result=$(fact $num)
echo "$num 的阶乘结果为:$result" 

Shell 脚本之函数及数组_第9张图片

1.6.2 递归目录

方法一

[root@localhost hanshu]# vim hanshu7.sh

#!/bin/bash
#递归/root/bin目录,显示它的所有子目录和文件
list() {
  for fd in $1/*
  do
   if [ -d $fd ];then
     echo "$fd是目录"
     list "$fd"
   else
     echo "$fd是文件"
   fi
  done
}

############# main #############
list "/root/bin"

Shell 脚本之函数及数组_第10张图片
方法二

#!/bin/bash
#递归/root/bin目录,显示它的所有子目录和文件
list() {
  #逐个检查$1参数指定目录下的所有文件或子目录
  for fd in $(ls $1)
  do
   #判断如果是目录就输出,并且通过递归把这个目录下的所有文件或子目录再逐个检查一下,>如果发现还有子目录会按照这个方式一直检查下去
   if [ -d "$1/$fd" ];then
     echo "$2$fd是目录"
     #在递归函数调用时第二个位置参数$2前面加的两个空格是为让每一次递归都在文件名前多加两个空格,使输出看起来有层次关系
     list "$1/$fd" "  $2"
   else
     echo "$2$fd是文件"
   fi
  done
}
############# main #############
#输出两个变量,$1:/root/bin和$2:空格
list "/root/bin" ""

Shell 脚本之函数及数组_第11张图片

1.7 函数库

可以事先创建一个函数库文件,在里面定义各种常用的函数,然后可以在别的shell脚本中直接引用这个函数库文件,使得不需要再次定义函数即可直接调用函数

创建一个函数库文件

[root@localhost hanshu]# vim hanshu9.sh
jiafa() {
  echo $[$1 + $2]
}

jianfa() {
  echo $[$1 - $2]
}

chengfa() {
  echo $[$1 * $2]
}

chufa() {
#判断除数是否等于0
  if [ $2 -eq 0 ];then
    echo "除数不能为0"
  else
    echo $[$1 / $2]
  fi
}

fact() {
  if [ $1 -eq 1 ];then
    echo 1
  else
    local temp=$[$1 - 1]
    local result=$(fact $temp)
    echo $[$1 * $result]
  fi
}

Shell 脚本之函数及数组_第12张图片
引用函数库文件

#!/bin/bash
#使用.或者source调用函数库
. hanshu9.sh

#定义两个值
v1=10
v2=5

#调用函数
res1=$(jiafa $v1 $v2)
res2=$(jianfa $v1 $v2)
res3=$(chengfa $v1 $v2)
res4=$(chufa $v1 $v2)
res5=$(fact $v1)

echo "加法结果为:$res1"
echo "减法结果为:$res2"
echo "乘法结果为:$res3"
echo "除法结果为:$res4"
echo "${v1}阶乘结果为:$res5"

Shell 脚本之函数及数组_第13张图片

2 数组

2.1 shell数组的定义

  • 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组)
  • 数组元素的下标由 0 开始
  • Shell 数组用括号来表示,元素用 “空格” 符号分割开
  • 在Shell语句中,使用、遍历数组的时候,数组格式要写成 ${arr[@]} 或 ${arr[*]}

2.2 定义和获取数组

定义数组
方法一:
数组名=(value0 valuel value2..)  //以空格间隔,如果值为字符类型,需要加单引号或双引号

方法二:
列表名="value0 value1 value2.."
数组名=($列表变量)

方法三:
数组名=[0]=value [1]=value [2]=value...)  //以空格间隔,n代表元素的下标,第一元素的下标从0开始

方法四:
数组名[n]=值   //n代表元素的下标,第一元素的下标从0开始
数组名[0]="value"
数组名[1]="value”
数组名[2]="value"

获取数组的所有元素的值,以列表形式输出的
${数组名[*]}
S{数组名[@]}

Shell 脚本之函数及数组_第14张图片

2.3 获取数组的长度及获取某一个元素的值

获取数组的长度
${#数组名[*]}
${#数组名[@]}

获取数组的某一个元素的值
${数组名[n]}  //n代表元素的下标,范围为0~长度减一

Shell 脚本之函数及数组_第15张图片

2.4 判断数组是否完整

${数组名[数组长度]}   //如果此值为空,则代表数组完整,因为最后一个元素的下标是数组长度减一

Shell 脚本之函数及数组_第16张图片
在这里插入图片描述

2.5 数组遍历

#!bin/bash
array=(10 20 30 40 50)
length=${#array[*]}
for ((i=0;i<=length-1;i++))
  do
    echo ${array[$i]}
  done
echo "-------------分割线-----------"
for j in ${array[*]}
do
  echo $j
done

Shell 脚本之函数及数组_第17张图片

2.6 数组分片、截取

${数组名[@]:起始位置:截取长度}   //起始位置是从0算起的

Shell 脚本之函数及数组_第18张图片

2.7 数组字符替换

${数组名[@]/旧字符/新字符}  //会替换所有元素上能匹配到的字符,但是这是临时替换不会影响原有数组,可通过重新赋值实现替换原有数组(数组名=(${数组名[@]/旧字符/新字符}))

Shell 脚本之函数及数组_第19张图片

2.8 删除数组和追加数组元素

删除数组
unset 数组名[n]   //删除某一个元素
unset 数组名[*]或者[@]   //删除某一个元素

追加数组
方法一:数组名[数组长度]=元素值
方法二:数组名+=(元素1 元素2....)
方法三:数组名=("${数组名[@]}" 元素1 元素2...)  //确定数组是完整的
方法四:数组名[${#数组名[*]}]=元素1 元素2...

Shell 脚本之函数及数组_第20张图片
字符追加
Shell 脚本之函数及数组_第21张图片

2.9 向函数传数组参数

向函数传数组参数?获取函数中数组的值,并在函数外重新组合成数组?(看下面的例2中的方法二)

第一步:向函数传入数组的时候需要先把数组转换成列表作为函数参数使用 
函数名 ${数组名1[@]}

第二步:在函数内把传入的列表重新组合成数组   数组名2=($@)

第三步:在函数外重新组合成数组   
数组名3=(`函数名 ${数组名1[@]}`

例1:

#!/bin/bash 
myfun() {
#若是$1,则只输出第一个数
  echo "函数接收到的参数为:$@"
#用括号扩起来组成起的数组
  newarr=($@)
  echo "新数组的值为:${newarr[@]}"
}
############### main #################
arr=(3 1 4 2 6 5)
echo "原数组的值为:${arr[@]}"
#把数组转换成列表给函数调用
myfun ${arr[@]}

Shell 脚本之函数及数组_第22张图片
例2:
方法一

#!/bin/bash 
myfun() {
  newarr=($@)
  echo "新数组的值为:${newarr[@]}"
  #也可用for ((i=0;i<=$[$# - 1];i++)),$#代表变量传进来的参数个数,就是数组的长度
  for ((i=0;i<=${#newarr[@]}-1;i++))
  do
    newarr[$i]=$[${newarr[$i]} * 2]
  done
  echo "结果为:${newarr[@]}"
}
############### main #################
arr=(3 1 4 2 6 5)
echo "原数组的值为:${arr[@]}"
#把数组转换成列表给函数调用
myfun ${arr[@]}

Shell 脚本之函数及数组_第23张图片
方法二

#!/bin/bash 
myfun() {
  newarr=($@)
  #也可用for ((i=0;i<=$[$# - 1];i++)),$#代表变量传进来的参数个数,就是数组的长度
  for ((i=0;i<=${#newarr[@]}-1;i++))
  do
    newarr[$i]=$[${newarr[$i]} * 2]
  done
  echo ${newarr[@]}
}
############### main #################
arr=(3 1 4 2 6 5)
echo "原数组的值为:${arr[@]}"
#向函数传入数组的时候需要先把数组转换成列表,获取从函数返回的数组时需要把返回的列表重新定义>成数组      
result=(`myfun ${arr[*]}`)
echo "函数处理后数组的值为:${result[@]}"

Shell 脚本之函数及数组_第24张图片
例3:把原数组的所有元素传入函数变成数组后再求出累加和

#!/bin/bash 
myfun() {
  newarr=($@)
  sum=0
  for i in ${newarr[@]}
  do
    sum=$[sum+i]
  done
  echo "数组内所有元素的累加和是:$sum"
}
############### main #################
arr=(3 1 4 2 6 5)
echo "原数组的值为:${arr[@]}"
#向函数传入数组的时候需要先把数组转换成列表
myfun ${arr[@]}

Shell 脚本之函数及数组_第25张图片

你可能感兴趣的:(shell脚本,函数,数组,函数,数组,递归)