一、函数
1、函数的概念
定义:将命令序列按照格式写在一起。
作用:方便重复使用。
函数库,集中在一起,随时可以传参使用,大的工程分割成若干个小的功能模块,提供代码的可读性
函数格式:
第一种
function 定义的方法名{
命令序列
}
第二种
定义的方法名(){ 命令序列 }定义名(调用传参)
2、返回码
function abc {
num=$(($a*2))
return $num
}
a=10
abc
echo $?
#这里的$?不在具有判断执行结果,只是一个函数内部的返回值
return只能写在函数内部
目的:从函数的内部获取一个返回值,用来判断是否继续执行下一个脚本
在使用return传返回码的时候,默认0是成功,非0都是失败,返回码的值0-255之间,超过了会除256取余数,可以自定义
function abc {
read -p "数" a
if [[ $a -eq $a ]] &> /dev/null
then
num=$(($a*2))
return 0
else
echo "输入错误"
return 1
fi
}
abc
if [[ $? -eq 0 ]]
then
echo ok
else
echo no
fi
3、 函数的传参方式已经函数变量的作用范围
1、传参方式
定义值
abc () {
num=$(($a+$b))
echo $num
}
read -p "第一个" a
read -p "第二个" b
abc
~
第二种方式
abc () {
num=$(($1+$2))
echo $num
}
abc $1 $2
2、函数变量的作用范围
abc () {
a=4
b=4
}
a=2
b=9
abc
ehco $a
echo $b
在函数内部定义了全局变量,
外部的赋值是不能改变内部函数的全局变量的
输出结果
a=4
b=4
abc () {
local a=4
local b=4
c=10
}
a=2
b=9
c=1
abc
echo $a
echo $b
echo $c
加了local之后就是函数内部的变量,而不是全局变量,外部的赋值会替换内部的变量值
输出
a=2
b=9
c=10
函数递归:函数调用自己本身的函数
实例:用函数递归的方式实现阶乘
abc () {
if [[ $1 -eq 1 ]]
then
echo 1
else
local temp=$(($1-1))
local result=$(abc $temp)
echo "$(($1*$result))"
fi
}
read -p "请输入你要计算的数字:" num
result1=`abc $num` #``将运算出来的结果作为一个字符串进行输出
echo $result1
实例:用函数递归的方式实现递归目录到没有文件为止
递归目录,直到目录里面没有文件为止
jiecheng () {
for file in `ls $1`
do
#-d 测试目录
if [[ -d "$1/$file" ]]
then
echo $file
jiecheng "$1/$file"
else
echo "不是一个目录$file"
fi
done
}
jiecheng $1
4、函数库
函数库中只包含定义的函数,由另外一个脚本传入参数来调用我们定义的函数
实例:小数+整数都可以运算 小数点后两位
jiafa () {
result=$(echo "$1 + $2" | bc)
#结果保留两位小数
printf "%.2f\n" "$result"
}
jianfa () {
result=$(echo "$1-$2" | bc)
#结果保留两位小数
printf "%.2f\n" "$result"
}
chengfa () {
result=$(echo "$1*$2" | bc)
#结果保留两位小数
printf "%.2f\n" "$result"
}
chufa () {
if [[ $2 -eq 0 ]]
then
echo "除数不能为0"
else
result=$(echo " $1/$2" | bc)
#结果保留两位小数
printf "%.2f\n" "$result"
}
调用函数 文件名diaoyong3.sh
. /opt/hanshu3.sh
read -p "输入第一个数:" num1
read -p "输入第一个数:" num2
sum=`jiafa $num1 $num2`
sub=`jianfa $num1 $num2`
mult=`chengfa $num1 $num2`
div=`chufa $num1 $num2`
echo $sum
echo $sub
echo $mult
echo $div
运行调用函数前需要给函数库赋可执行权限
二、数组
1、数组的概念
数组:在集合当中指定多个元素,元素的类型:整数,字符串,可以是浮点
作用:一次性定义多个元素,可以位变量赋值提供便利
数组的定义方法:
数组名=(元素值) 数组名不能重复
数组名=(a b c d)
打印数组值echo ${数组名[* ]}或者echo ${数组名[@]}
#两种定义的方法
[root@localhost opt]# test1=(a b c d)
[root@localhost opt]# echo ${test1[*]}
a b c d
#[0]中的0表示下标,从0开始
[root@localhost opt]# test[0]=1
[root@localhost opt]# test[1]=2
[root@localhost opt]# test[2]=3
[root@localhost opt]# echo ${test[*]}
1 2 3
数组的长度指的是数组内包含了几个元素
echo ${#test[*]} 或者echo ${#test[@]}
#test内包含了3个文件
[root@localhost opt]# echo ${#test[*]}
3
查看数组第几个内容
[root@localhost opt]# test3=(11 22 33)
[root@localhost opt]# echo ${test3[0]}
11
[root@localhost opt]# echo ${test3[1]}
22
[root@localhost opt]# echo ${test3[2]}
33
对数组进行遍历
#对数组进行遍历
test4=(aa bb cc dd)
for i in ${test4[*]}
do
echo $i
done
结果
[root@localhost opt]# sh shuzu1.sh
aa
bb
cc
dd
对数组进行切片
[root@localhost opt]# test5=(1 2 3 4 5)
#0表示起始位置,2表示步长,起始位置0开始,包括0移动2个
[root@localhost opt]# echo ${test5[*]:0:2}
1 2
[root@localhost opt]# echo ${test5[*]:1:3}
2 3 4
[root@localhost opt]# echo ${test1[*]}
a b c d
[root@localhost opt]# echo ${test1[*]:1:1}
b
[root@localhost opt]# echo ${test1[*]:1:2}
b c
2、数组替换
临时替换,不会真正改变数组值
[root@localhost opt]# echo ${test5[*]/1/a}
a 2 3 4 5
[root@localhost opt]# echo ${test5[*]}
1 2 3 4 5
永久修改,通过修改元素下标的值可以实现
[root@localhost opt]# test5[0]=b
[root@localhost opt]# echo ${test5[*]}
b 2 3 4 5
[root@localhost opt]# test5[4]=e
[root@localhost opt]# echo ${test5[*]}
b 2 3 4 e
3、删除数组
删除整个数组
[root@localhost opt]# unset test1
[root@localhost opt]# echo ${test1[*]}
[root@localhost opt]#
删除数组中的元素,元素下标的值不会发生变化
[root@localhost opt]# unset test5[0]
[root@localhost opt]# echo ${test5[*]}
2 3 4 e
[root@localhost opt]# echo ${test5[0]}
[root@localhost opt]# echo ${test5[1]}
2
4、数组中进行追加
#根据元素下标,指定追加
[root@localhost opt]# echo ${test5[*]}
2 3 4 e
[root@localhost opt]# test5[0]=a
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 e
[root@localhost opt]# test5[6]=9
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 e 9
#自动追加
[root@localhost opt]# test5+=(qq oo)
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 e 9 qq oo
#追加只能在最后开始追加,中间缺失的部分不会补齐
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 e 9 qq oo
[root@localhost opt]# unset test5[4]
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 9 qq oo
[root@localhost opt]# test5+=(ddd)
[root@localhost opt]# echo ${test5[*]}
a 2 3 4 9 qq oo ddd
[root@localhost opt]# echo ${test5[4]}
实例:定义一个数组,元素都是整数,实现数字内整数的累加求和
sum=0
test1=(10 20 30 40 50)
for i in ${test1[*]}
do
sum=$(($sum+$i))
done
echo $sum
实例:定义一个数组,元素都是整数,分别求出偶数,奇数累加求和
sum1=0
sum2=0
test1=(10 15 40 61 31 42)
for i in ${test1[*]}
do
if [[ $((i%2)) -eq 0 ]]
then
sum1=$(($sum1+$i))
else
sum2=$(($sum2+$i))
fi
done
echo "偶数的和为:$sum1"
echo "奇数的和为:$sum2"
运行结果
[root@localhost opt]# sh shuzu2.sh
偶数的和为:92
奇数的和为:107
实例:定义一个数组,并取出一个最小值,最大值
test1=(3 5 7 4 1)
max=${test1[0]}
min=${test1[0]}
for i in ${test1[*]}
do
if [[ $i -gt $max ]]
then
max=$i
fi
if [[ $i -lt $min ]]
then
min=$i
fi
done
echo "max=$max"
echo "min=$min"
结果
[root@localhost opt]# sh shuzu2.sh
max=7
min=1
5、冒泡排序
冒泡排序类似于气泡上涌的工作,会将数组当中的元素按照从小到大,或者从大到小的顺序进行一个重新排列
从小到大排
思路:对比两个相邻的元素,以从下到大为例,满足交换条件的元素,小的往左移,大的往右移动
数组的位置发生变化(下标对应的元素的值发生变化)
双层循环,外部循环控制排序的轮次,内部循环用来对比两个元素的大小,决定是否互换位置
对比和交换的次数随着排序轮次而减少
实例:使用冒泡排序将test1的内容进行从小到大进行排序
test1=(20 10 60 40 50 30)
len=${#test1[*]}
#定义排序的轮次
for ((i=1;i<$len;i++))
do
for ((k=0;k<$len-i;k++))
do
#定义第一个数组的值
first=${test1[$k]}
j=$(($k+1))
#定义第二个下标位置
second=${test1[$j]}
if [ $first -gt $second ]
then
#交换位置
temp=$first
test1[$k]=$second
test1[$j]=$temp
fi
done
echo "排序后的数组值为:${test1[*]}"
done
实例:使用冒泡排序将df的已用进行从大到小进行排序
# 取出已用并将%去掉
test1=($(df -h | awk 'NR>1 {print $5}' | tr -d '%'))
len=${#test1[*]}
#定义排序的轮次
for ((i=1;i<$len;i++))
do
for ((k=0;k<$len-i;k++))
do
#定义第一个下标的值
first=${test1[$k]}
j=$(($k+1))
#定义第二个下标位置
second=${test1[$j]}
if [ $first -le $second ]
then
#交换位置
temp=$first
test1[$k]=$second
test1[$j]=$temp
fi
done
done
echo "排序后的数组值为:${test1[*]}"