【shell】脚本中的函数和数组

一、函数

        函数可以理解为脚本的别名,使用函数可以避免代码错误,增强可读性,简化脚本;函数可以将大的工程来分割为若干小的功能模块,代码的可读性更强;

1、函数语法

格式1
function 函数名 {
    命令序列
}
 
 
格式2
函数名() {
    命令序列
}

2.1  基础操作

# 查看当前已定义的函数名 
declare -F 
# 查看当前已定义的函数定义 
declare -f 
# 查看指定当前已定义的函数名 
declare -f func_name 
# 查看当前已定义的函数名定义 
declare -F func_name

2.2  注意事项

(1)同名函数调用后一个生效

(2)调用函数前要先定义

(3)每个函数是独立的

(4)在函数中调用函数直接写函数名即可 

2、函数返回值

        return表示退出函数并返回一个退出值,脚本中可以用$?变量表示该值

2.1  使用原则

(1)函数一结束就取返回值,因为$?变量只返回最后一条命令的退出状态码

(2)退出状态必须是0-255,超出时值将为256取余

2.2  示例

【shell】脚本中的函数和数组_第1张图片

3、函数传参

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

【shell】脚本中的函数和数组_第2张图片

4、函数变量的作用范围

(1)函数在shell脚本中仅在当前Shell环境中有效

(2)Shell脚本中变量默认全局有效

(2)将变量限定在函数内部使用local命令

举例:

【shell】脚本中的函数和数组_第3张图片

5、函数调用 

(1)可在交互式环境下定义函数

(2)可将函数放在脚本文件中作为它的一部分

(3)可放在只包含函数的单独文件中

位置调用 

【shell】脚本中的函数和数组_第4张图片

【shell】脚本中的函数和数组_第5张图片【shell】脚本中的函数和数组_第6张图片

【shell】脚本中的函数和数组_第7张图片

例1: 使用函数的方式,将标准输入获得十进制ip地址转换为二进制的ip地址

#!/bin/bash
 
#定义一个用于十进制转化成二进制的函数
function bin {
SUM=''
NUM=$1
for i in {1..8}
do
   SUM=$[NUM%2]$SUM
   let NUM/=2
done
echo $SUM
}
 
#定义一个用分割IP的函数
SPT (){
   IP=$1
   for i in {1..4}
   do
   num=${IP%%.*}
   IP=${IP#*.}
   #使用bin函数进行转化
   BIN=$(bin $num)
   echo -n $BIN.
   done
}
 
####################main##################
read -p "请输入一个十进制的IP地址:"   SIP
RES=$(SPT $SIP)
echo  "输出的二进制IP为:"   ${RES%.*}

例2:使用函数打印一个菱形,要求能够通过标准输入的方式来控制菱形的大小

#!/bin/bash
 
#用来打印菱形上半部分的函数
shang (){
i=1
NUM=$1
while [ $i -le $NUM ]
do
  a=$NUM
  while [ $a  -ge  $i ]
  do
  echo -n  ' '
  let a--
  done
  b=1
  while [ $b -le  $i ]
  do
  echo -n '*'
  let b++
  done
  c=2
  while [ $c -le  $i   ]
  do
  echo -n '*'
  let c++
  done
echo ""
let i++
done
}
#用来打印菱形下半部分的函数
xia (){
let d=$1-1
while [ $d -ge 1  ]
do
 e=$1
 while [ $e -ge $d ]
 do
 echo -n ' '
 let e--
 done
 f=$[(2*d)-1]
 g=1
 while [ $g -le $f ]  
 do
 echo -n '*'
 let g++
 done
let d--
echo ""
done
}
 
######################main#####################
read -p  "请输入一个数字来控制函数的大小(数字越大菱形越大):"    num
 
shang $num
 
xia   $num

6、递归调用

        递归函数就是调用自己本身的函数,递归调用一定要有结束函数的语句,否则将导致死循环。

例1:函数实现阶乘运算

[root@clr /opt/mywork]# vim 3.sh
 
#!/bin/bash
#使用函数的递归实现阶乘
 
fact() {
  if [ $1 -eq 1 ];then
    echo 1
  elif [ $1 -gt 1 ];then
    local tmp=$[$1 - 1]
    local res=$(fact $tmp)  #在函数内调用函数
    echo $[$1 * res]
  else
    echo "输入的值无效。请输入大于等于1的整数!"
  fi
}
 
#####main#####
 
read -p "请输入一个大于等于1的整数:" num
res=$(fact $num)
echo "$num的阶乘值为$res"

例2:通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件

#!/bin/bash
#通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件
 
#定义一个遍历PATH环境变量的函数
list_path() {
    IFSB=$IFS
    IFS=$IFS':'
    for F in $PATH
    do
        echo "$F"
    done
    IFS=$IFSB
}
 
#定义一个递归函数
listf() {
    for F in $(ls $1)
    do
        if [ -d "$1/$F" ];then
            echo "$2$F"
            listf "$1/$F" "  $2"
        else
            if [ ! -x "$1/$F" ];then
                echo "$2$F"
            fi
        fi
    done
}
 
######main######
#获取PATH变量的所有目录列表
folder=$(list_path)
 
#遍历PATH变量的目录,并用函数递归查询
for path in $folder
do
    echo $path
    listf "$path" "  "
done

二、数组

2.1  语法定义

        语法一:数组名=(value0 value1 value2 ...) 

[root@localhost ~]# array1=(10,20,30,40,50)
[root@localhost ~]# echo ${array1[@]}
10,20,30,40,50

        语法二:数组名=([0]=value [1]=value [2]=value ...)

[root@localhost ~]# array2=([0]=10 [1]=20 [2]=30 [3]=40 [4]=50)
[root@localhost ~]# echo ${array2[*]}
10 20 30 40 50

        语法三:列表名="value0 value1 value2 ..."
                      数组名=($列表名)

[root@localhost ~]# list="11 22 33 44 55"
[root@localhost ~]# array2=($list)
[root@localhost ~]# echo ${array2[@]}
11 22 33 44 55

        语法四:数组名[0]="value"
                    数组名[1]="value"
                    数组名[2]="value"

[root@localhost ~]# array3[0]=10
[root@localhost ~]# array3[1]=20
[root@localhost ~]# array3[2]=30
[root@localhost ~]# array3[3]=40
[root@localhost ~]# array3[4]=50
[root@localhost ~]# echo ${array3[@]}
10 20 30 40 50

2.2  基本操作

2.2.1  数组元素的输出

1、默认输出第一个数组元素

     格式:echo ${数组名} 

2、输出对应下标元素

     格式 :echo ${数组名[下标]} 

3、输出整个数组的元素   

     格式一:echo ${数组名[*]}

     格式二:echo  ${数组名[@]}

[root@localhost ~]# echo ${array2[*]}
11 22 33 44 55
[root@localhost ~]# echo ${array2[@]}
11 22 33 44 55
[root@localhost ~]# echo ${array2}
11
[root@localhost ~]# echo ${array2[1]}
22

2.2.2  数字下标列表的获取

        格式:echo ${!数组名[@]} 

                   echo ${!数组名[*]}

[root@localhost ~]# echo ${!array2[@]}
0 1 2 3 4
[root@localhost ~]# echo ${!array2[*]}
0 1 2 3 4

2.2.3  数组长度的获取

        格式:echo ${#数组名[*]} 

                   echo ${#数组名[@]} 

[root@localhost ~]# echo ${#array2[*]}
5
[root@localhost ~]# echo ${#array2[@]}
5

2.2.4  数组切片

        格式一:echo ${数组名[*]:下标:个数}            #获取 ${数组名[@或*]:起始位置:长度} 的值

        格式二:echo ${数组名[@]:下标:个数}

[root@localhost ~]# echo ${array2[@]}
11 22 33 44 55
[root@localhost ~]# echo ${array2[@]:2:2}
33 44

2.2.5  数组元素的替换

         格式:${数组名[@或*]/查找字符/替换字符}            

         注:该命令并不会替换数组原有内容,要实现改变原有数组,可通过重新赋值实现

arr=(1 2 3 4 5)
echo ${arr[@]/1/66}  #令{数组名[@或*]/查找字符/替换字符}
echo ${arr[@]}       #并不会替换数组原有内容
 

2.2.6  删除数组

arr=(1 2 3 4 5)
unset arr				#删除整个数组
echo ${arr[*]}
 
arr=(1 2 3 4 5)
unset arr[2]			#删除第三个元素,即下标为2的元素
echo ${arr[*]}

2.2.7  数组元素的追加

        方法一:array_name[index]=value

        方法二:array_name[${#array_name[@]}]=value

        方法三:array_name=("${array_name[@]}" value1 ... valueN)

注:双引号不能省略,否则,当数组array_name中存在包含空格的元素时会按空格将元素拆分成多个;不能将“@”替换为“*”,如果替换为“*”,不加双引号时与“@”的表现一致,加双引号时,会将数组array_name中的所有元素作为一个元素添加到数组中

        方法四:array_name+=(value1 ... valueN)

注:待添加元素必须用“()”包围起来,并且多个元素用空格分隔

2.2.8  数组元素的删除

arr=(1 2 3 4 5)
unset arr       #删除数组
echo ${arr[*]}
 
arr=(1 2 3 4 5)
unset arr[2]    #删除第三个元素
echo ${arr[*]}

2.2.9  数组参数的传递

###如果将数组变量作为函数参数,函数只会取数组变量的第一个值
test1(){
      echo "接收到的参数列表:$@"
      newarr=($1)
      echo "新数组的值为:${newarr[*]}"
}
###########main############
arr=(1 2 3 4 5)
echo "原始数组的值为:${arr[*]}"
test $arr
 
###解决这个问题则需要将数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,再将所有的参数重新组合成一个新的数组变量
test2(){
	newarr=($(echo $@))
	echo "新数组的值为:${newarr[*]}"
}
array=(1 2 3 4 5)
echo"原始数组的值为:${array[*]}"
test1 ${array[*]}

你可能感兴趣的:(shell脚本,linux,运维,bash)