文章目录
- 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
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
例2:
#!/bin/bash
sum2 () {
#函数中的 $1 $2 代表调用函数时,函数后面跟的位置参数
echo $1
echo $2
}
########### main ##########
#主体代码中的 $1 $2 代表执行脚本时,脚本后面跟的位置参数
sum2 $2 $1
1.5 函数变量的作用范围
- 函数在Shell脚本中仅在当前shell环境中有效
- Shell脚本中变量默认全局有效
- 将变量限定在函数内部使用local命令
例1:全局有效
例2:函数内部使用
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"
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"
方法二
#!/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" ""
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
}
引用函数库文件
#!/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"
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{数组名[@]}
2.3 获取数组的长度及获取某一个元素的值
获取数组的长度
${#数组名[*]}
${#数组名[@]}
获取数组的某一个元素的值
${数组名[n]} //n代表元素的下标,范围为0~长度减一
2.4 判断数组是否完整
${数组名[数组长度]} //如果此值为空,则代表数组完整,因为最后一个元素的下标是数组长度减一
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
2.6 数组分片、截取
${数组名[@]:起始位置:截取长度} //起始位置是从0算起的
2.7 数组字符替换
${数组名[@]/旧字符/新字符} //会替换所有元素上能匹配到的字符,但是这是临时替换不会影响原有数组,可通过重新赋值实现替换原有数组(数组名=(${数组名[@]/旧字符/新字符}))
2.8 删除数组和追加数组元素
删除数组
unset 数组名[n] //删除某一个元素
unset 数组名[*]或者[@] //删除某一个元素
追加数组
方法一:数组名[数组长度]=元素值
方法二:数组名+=(元素1 元素2....)
方法三:数组名=("${数组名[@]}" 元素1 元素2...) //确定数组是完整的
方法四:数组名[${#数组名[*]}]=元素1 元素2...
字符追加
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[@]}
例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[@]}
方法二
#!/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[@]}"
例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[@]}