函数可以理解为脚本的别名,使用函数可以避免代码错误,增强可读性,简化脚本;函数可以将大的工程来分割为若干小的功能模块,代码的可读性更强;
格式1
function 函数名 {
命令序列
}
格式2
函数名() {
命令序列
}
# 查看当前已定义的函数名
declare -F
# 查看当前已定义的函数定义
declare -f
# 查看指定当前已定义的函数名
declare -f func_name
# 查看当前已定义的函数名定义
declare -F func_name
(1)同名函数调用后一个生效
(2)调用函数前要先定义
(3)每个函数是独立的
(4)在函数中调用函数直接写函数名即可
return表示退出函数并返回一个退出值,脚本中可以用$?变量表示该值
(1)函数一结束就取返回值,因为$?变量只返回最后一条命令的退出状态码
(2)退出状态必须是0-255,超出时值将为256取余
#!/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
(1)函数在shell脚本中仅在当前Shell环境中有效
(2)Shell脚本中变量默认全局有效
(2)将变量限定在函数内部使用local命令
举例:
(1)可在交互式环境下定义函数
(2)可将函数放在脚本文件中作为它的一部分
(3)可放在只包含函数的单独文件中
位置调用
例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
递归函数就是调用自己本身的函数,递归调用一定要有结束函数的语句,否则将导致死循环。
例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
语法一:数组名=(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
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
格式:echo ${!数组名[@]}
echo ${!数组名[*]}
[root@localhost ~]# echo ${!array2[@]}
0 1 2 3 4
[root@localhost ~]# echo ${!array2[*]}
0 1 2 3 4
格式:echo ${#数组名[*]}
echo ${#数组名[@]}
[root@localhost ~]# echo ${#array2[*]}
5
[root@localhost ~]# echo ${#array2[@]}
5
格式一:echo ${数组名[*]:下标:个数} #获取 ${数组名[@或*]:起始位置:长度} 的值
格式二:echo ${数组名[@]:下标:个数}
[root@localhost ~]# echo ${array2[@]}
11 22 33 44 55
[root@localhost ~]# echo ${array2[@]:2:2}
33 44
格式:${数组名[@或*]/查找字符/替换字符}
注:该命令并不会替换数组原有内容,要实现改变原有数组,可通过重新赋值实现
arr=(1 2 3 4 5)
echo ${arr[@]/1/66} #令{数组名[@或*]/查找字符/替换字符}
echo ${arr[@]} #并不会替换数组原有内容
arr=(1 2 3 4 5)
unset arr #删除整个数组
echo ${arr[*]}
arr=(1 2 3 4 5)
unset arr[2] #删除第三个元素,即下标为2的元素
echo ${arr[*]}
方法一:array_name[index]=value
方法二:array_name[${#array_name[@]}]=value
方法三:array_name=("${array_name[@]}" value1 ... valueN)
注:双引号不能省略,否则,当数组array_name中存在包含空格的元素时会按空格将元素拆分成多个;不能将“@”替换为“*”,如果替换为“*”,不加双引号时与“@”的表现一致,加双引号时,会将数组array_name中的所有元素作为一个元素添加到数组中
方法四:array_name+=(value1 ... valueN)
注:待添加元素必须用“()”包围起来,并且多个元素用空格分隔
arr=(1 2 3 4 5)
unset arr #删除数组
echo ${arr[*]}
arr=(1 2 3 4 5)
unset arr[2] #删除第三个元素
echo ${arr[*]}
###如果将数组变量作为函数参数,函数只会取数组变量的第一个值
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[*]}