shell编程(二)——函数、递归函数、数组


一、shell函数定义

1、格式

将命令序列按格式写在一起,可方便重复使用命令序列
需要先定义函数名再调用,调用即在代码末写上函数名

格式一:

[ function ] 函数名(){
          命令序列
          [ return  X]
}

格式二:
一般应用时,省略“[ function ] ”

函数名(){
          命令序列
          [ return  X]
}

格式三:

function 函数名 {
}

2、实例

定义函数名叫hello,执行命令序列打印hello,要求输出hello
想要执行代码,需要把函数名写在最后面

  • 格式一
#!/bin/bash
function hello(){   ##定义函数名 hello
echo hello    ##命令序列
}
hello    ##调用函数
  • 格式二
#!/bin/bash
hello(){
echo hello
}
hello

3、调用函数

3.1、调用函数-脚本内

  • 函数是常量时,若要调用函数的结果,需要加反撇号
#!/bin/bash
hello(){
echo hello
}

world(){
echo world
}

nihao(){
echo `hello` `world`   ## 调用函数的结果,需要加反撇号
}

nihao

验证
在这里插入图片描述

  • 函数是变量时
    计算两个数的和;三种方式
#!/bin/bash
SUM(){
a=2
b=3
let sum=$a+$b
echo $sum
}
SUM
#! /bin/bash
sum(){
11
read -p  “请输入一个数值: ” a
read -p  “请输入一个数值: ” b
let sum=$a+$b
echo $sum
sum
SUM(){
let sum=$1+$2   ##脚本的位置变量$1和$2
echo $sum
}

SUM $1 $2  ##把脚本的$1$2调用给SUM

验证结果
在这里插入图片描述

3.2、调用函数-脚本外

  • 先赋值后调用
    当前shell环境内变量a=20
    在这里插入图片描述
aaa(){
a=10
echo $a
}
a=20    ## 给a赋值220
aaa     ## 此时的aaa是a=10的变量,输出10
echo $a  ##   这时a的变量值为10.再次输出10

在这里插入图片描述

  • 先调用后赋值
    在这里插入图片描述
  • 若一定要定义脚本内变量和脚本外的变量同名的话,需要脚本内的变量加上“local”,否则会跟脚本外的冲突;local作用范围仅在函数内部,不会对外部有影响
    当前shell环境内变量a=20
    在这里插入图片描述
    这时脚本内的变量a=10,脚本内变量前面加上“local”之后发现输出的结果是 10;20
    在这里插入图片描述
    在这里插入图片描述
  • 使用同名函数,后面的内容会被前面覆盖掉,所以函数名尽量不要一样
    在这里插入图片描述

在这里插入图片描述

  • 在一个脚本调用另外一个脚本的内容,需要使用source 绝对路径,刷新环境
    先编辑脚本 hello.sh 函数名是www,输出world在这里插入图片描述
    这时在当前脚本需要刷新环境,再调用即可
    在这里插入图片描述
    在这里插入图片描述

3.2、调用函数-返回状态码

当一条命令执行成功,返回状态码为0,那若有多条命令时,如何取值呢?

  • 返回码的结果取值函数的最后一条命令的返回结果

实例看下结果
在这里插入图片描述
调用hello成功了,但是lsxxx不成功,所以 echo $? 返回码是2,非0值
在这里插入图片描述
这时把ls xxxxx 放在命令序列内,查看返回码仍是非0值
在这里插入图片描述

在这里插入图片描述

  • 使用return自定义一个返回码的值,值的范围0~255

不论脚本内的函数是否成功,均返回自定义返回码;此方法可以定位到具体的脚本,若脚本出错,直接找到对应定义的范围码位置即可
自定义返回码为20
在这里插入图片描述

在这里插入图片描述

  • 脚本内看到ruturn就结束,这里返回码是10
    在这里插入图片描述

在这里插入图片描述

4、实例

  • 判断文件是否存在,存在返回该文件已存在,不存在返回该文件不存在
    • 第一种
      在这里插入图片描述
      在这里插入图片描述
    • 第二种
      使用位置变量
      在这里插入图片描述
      在这里插入图片描述
  • 计算用户指定的1-?的和
    计算用户指定的1-?的偶数和
    根据用户需求选择算总和还是偶数
#!/bin/bash
SUM(){
read -p "请输入你想计算1-几的和: " num
sum=0
for i in `seq $num`   ##seq是一个序列的缩写,主要用来输出序列化的东西
do
let sum=$i+$num
done
echo $sum
}

oushu(){
read -p "输入你想计算1到几的偶数和:" n
sum=0
for i in `seq $n`
do
if [ $((i%2)) -eq 0 ];then
        let sum=$i+$sum
fi
done
echo $sum
}

if [ $1 == 总和 ];then
SUM
elif [ $1 == 偶数 ];then
oushu
else
echo "参数错误"
fi

在这里插入图片描述

  • 计算阶乘
    • 第一种方法
#!/bin/bash
jiecheng(){
read -p "请输入几的阶乘:" num
cheng=1
for i in `seq $num`
do
let cheng=$i*$cheng
done
echo $cheng
}

jiecheng

在这里插入图片描述

  • 第二种方法(位置变量)
#!/bin/bash
jiecheng(){
read -p "请输入几的阶乘:" num
cheng=1
for i in `seq $1`
do
let cheng=$i*$cheng
done
echo $cheng
}

jiecheng  $1

在这里插入图片描述

二、递归函数

调用自己本身的函数

1、遍历文件夹

list_files( : : Directory, Options : Files)

Directory:目录(文件夹路径)

Options:选项

files  ##指定搜索的格式为文件
directories  ##指定搜索的格式为文件夹
recursive  ##指定可以遍历子文件夹下的文件
follow_links
max_depth 5  ##指定遍历的深度
max_files 1000  ##指定遍历的最大文件数目

Files:文件(文件的路径)

2、文件格式筛选

tuple_regexp_select( : : Data, Expression : Selection)

Data:被选择的文件路径数组

Expression:文件格式的筛选规则

\   ##转义 
(bmp|JPG) ##筛选的文件格式
ignore_case  ##忽略大小写

Selection  ##选择出的文件路径数组

3、实例

  • 利用shell脚本遍历指定路径下etc的所有文件
    [root@localhost opt]# vim xc4.sh
#!/bin/bash
function list_files {    ##定义递归遍历目录的函数
for f in `ls $1`     ##循环遍历目录
do
        if [ -d "$1/$f" ]
        then          ##判断若为目录则按格式输出目录名称并继续调用函数遍历这个目录
                echo "$2$f"
                list_files "$1/$f" "$2"
        else           ##判断若为文件则直接按照格式输出文件名称
                echo "$2$f"
        fi
done
}

list_files "/var/log" ""   ##调用函数,第一个参数为要进行遍历的目录,第二个参数为格式设定,区分目录层级

验证
在这里插入图片描述

  • 用函数递归的方式实现遍历目录,并显示层级效果,目录显示蓝色
#!/bin/bash
list_files() {
        for f in `ls $1`
        do
                if [ -d "$1/$f" ]; then
                        echo -e "\e[34m"$2$f"\e[0m"
                        list_files "$1/$f""$2"
                else
                        echo "  $2$f"
                fi
        done
}
list_files "/var/log" ""

验证
在这里插入图片描述

三、数组

1、应用场景

  • 获取数组长度
  • 获取元素长度
  • 遍历元素
  • 元素切片
  • 元素替换
  • 元素删除

2、数组定义的方法

  • 方法一
    数组名=(value0 value1 value2…)
  • 方法二
    数组名=([0]=value [1]=value [3]=value…)
  • 方法三
    列表名=“value0 value1 value2…”
    数组名=($列表名)
  • 方法四
    数组名[0]=“value”
    数组名[1]=“value”
    数组名[2]=“value”

3、数组包括的数据类型

  • 数值类型
  • 字符类型
    • 使用“或”定义

4、实例

赋值一个数组
数组的下标第一个值是[0]
在这里插入图片描述
调用数组所有的下标

# ##显示有多少个
! ##显示数据的下标
echo ${a[*]}  ##查看数组内容
echo ${#a[*]}  ## 查看数组的个数
echo ${!a[@]}  ##查看数组的下标

在这里插入图片描述
echo ${fruit[]} ##查看数组的个数
echo ${fruit[4]} ##查看下标4的数组内容
在这里插入图片描述
更改数组其中一个变量值
fruit[4]=boluo
echo ${fruit[
]} ## 更改属主4为boluo
在这里插入图片描述
unset fruit[4] ## 删除数组[4]
在这里插入图片描述
查看索引,使用" ! "
在这里插入图片描述
在这里插入图片描述
查询系统有多少个用户

list=`cat /etc/passwd`
list1=($list)
echo ${#list1[*]}

在这里插入图片描述
元素切片

[root@klj ~]# a=(1 2 3 4 5)
[root@klj ~]# echo ${a[*]:2:3}   ##从第二个数组切片3个,显示的是下标
3 4 5
[root@klj ~]# echo ${a[*]:1:3}
2 3 4

在这里插入图片描述
元素替换

[root@klj ~]# echo ${a[*]/5/15}   ##搜索到数组5替换成15
1 2 3 4 15

在这里插入图片描述
利用数组打印1-5;三种方法

#!/bin/bash
a=(1 2 3 4 5)
for i in ${a[*]}
do
echo $i
done
#!/bin/bash
a=(1 2 3 4 5)
for ((i=0;i<${#a[*]};i++))
do
echo ${a[$i]}
done
#!/bin/bash
a=(1 2 3 4 5)
i=0
while [ $i -lt 5 ];
do
echo ${a[$i]}
let i++
done

验证
在这里插入图片描述
把1-10之间的偶数存到数组里面,并显示下标
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
现在有一个数组,a=(10 20 30 40 50),输出数组内最大的数
在这里插入图片描述
在这里插入图片描述
使用冒泡排序进行排序

#!/bin/bash
bubble(){
sum=(60 20 30 70 50)
   for((i=0;i<${#sum[*]}-1;i++))     ##已比出最大值
   do
        for((j=0;j<${#sum[*]}-i-1;j++))     ## ${#sum[*]}-i-1 -i:自身已经比过了,
        do
                if [ ${sum[$j]} -gt ${sum[`expr $j + 1`]} ]
                then
                temp=${sum[$j]}
                sum[$j]=${sum[`expr $j + 1`]}
                sum[`expr $j + 1`]=$temp
                fi
        done
  done
  for((i=0;i<${#sum[*]};i++))
  do
        echo -n "${sum[$i]}  "
  done
  echo ""
}
bubble

验证
在这里插入图片描述
把数组中不足60的加到60、删除数组中不足60分的元素

#!/bin/bash
num=(90 90 90 50 90 40 30 20)
for ((i=1;i<=${#num[*]};i++))
do
 if [ $[num[$i-1]] -lt 60 ]
then
  num[$i-1]=60
fi
done
echo ${num[*]}

在这里插入图片描述

#!/bin/bash
num=(90 50 60 45 30 90 90)
i=0
for j in ${num[*]}
do
if [ $j -lt 60 ]
then
unset num[$i]
fi
let i++
done
echo ${num[*]}

验证
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值