shell编程函数与数组
1、shell中函数
(1)shell中函数的语法
语法一:
函数名(){
指令
return n
}
语法二:
function 函数名(){
指令
return n
}
(2)shell中函数的调用执行
1)直接执行函数名即可,在执行函数时,不要带小括号,函数定义及函数体必须要在执行的函数名前定义。
2)带参数的函数的执行方法:函数名 参数1 参数2
(3)函数带参数的说明
1)在函数体重,位置函数都可以是函数的参数
2)父脚本的参数在函数中则临时地被函数参数所掩盖或隐藏
3)$0比较特殊,他任然是父脚本的参数,
4)在shell函数里面,return命令的工作方式与exit相同,用于跳出函数。
5)在shell函数里使用exit会终止整个shell脚本。
6)return语句会返回一个退出值给调用的程序
(4)递归:函数直接或间接的调用自身进行计算
1)递归求阶乘
#!/bin/sh
function jc(){
if [ $1 -eq 1 ]
then
echo "1"
else
echo $[ $1*$(jc $[$1-1]) ]
fi
}
jc $1
2)递归求斐波那契数列第N项的值
#!/bin/bash
function ad(){
if [ $1 -eq 1 ]
then
echo "1"
elif [ $1 -eq 2 ]
then
echo "1"
else
echo $[ $(ad $[$1-1])+$(ad $[$1-2])]
fi
}
ad $1
2、数组
(1)数组:存储多个元素的连续内空间间,相当于多个变量的集合
(2)数组的创建与声明:
1)定义一个数组:array=(“dayi123” 19)
2)声明一个数组:
声明索引数组:declare –a arrname
声明关联数组:declare –A arrname
[[email protected] ~]#arr1=("dayi123" 13 "string") #创建一个数组
[[email protected] ~]#declare -a arr2 #声明一个数组
[[email protected] ~]#arr2[0]="dayi" #往数组中添加元素
[[email protected] ~]# arr2[1]="18"
(3)获取数组的长度
echo ${#array[@]}
echo ${#array[*]}
[[email protected] ~]# echo${#arr1[@]} #打印数组中元素个数
3
[[email protected] ~]# echo${#arr2[*]} #打印数组中元素个数
1
(4)打印数组的元素
echo ${array[n]}
echo ${array[@]}
echo ${array[*]}
[[email protected] ~]# echo${arr1[1]} #打印数组arr1中的第2个元素
13
[[email protected] ~]# echo${arr1[0]} #打印数组arr1中的第1个元素
dayi123
[[email protected] ~]# echo${arr1[@]} #打印数arr1中的所有元素
dayi123 13 string
[[email protected] ~]# echo${arr2[*]} #打印宿主arr2中的所有元素
dayi123 22
(5)数组的赋值
数组的赋值:array[3]=4
修改数组元素:arrary[0]=”liuyi”
[[email protected] ~]#arr1[3]=4
[[email protected] ~]#arr1[0]="liu"
[[email protected] ~]# echo${arr1[*]}
liu 13 string 4
(6)数组内容的截取
echo ${arr1[@]:n:m} #截取第n个到第m个元素
[[email protected] ~]# echo${arr1[*]:1:2}
13 string
(7)数组内容的替换
echo ${arr1[@]/n/m} #将数组中的第一个n替换为m
[[email protected] ~]# echo${arr1[*]/"liu"/"dayi123"}
dayi123 13 string 4dayi123
(8)数组的删除与数组中元素的删除
unset array #删除整个数组
unset array[n] #删除数组中第n个元素,删除一个元素时只能从头开始一个一个删除
[[email protected] ~]# unsetarr1[0] #删除数组中第一个元素
[[email protected] ~]# echo${arr1[*]}
13 4 liu
[[email protected] ~]# unsetarr1[2] #直接删除数组中第二个元素,删不掉
[[email protected] ~]# echo${arr1[*]}
13 4 liu
[[email protected] ~]# unsetarr1[1] #删除数组中第一个元素,因为第0个元素已经删除
[[email protected] ~]# echo${arr1[*]}
4 liu
[[email protected] ~]# unsetarr1 #删除整个数组
[[email protected] ~]# echo${arr1[*]}
[[email protected] ~]#
(9)数组使用案例:
1)生成10个随机数,找出其中的最大值
#!/bin/sh
declare -a rand
declare -i max=0
for i in {0..9};do
rand[$i]=$RANDOM
echo ${rand[$i]}
[ ${rand[$i]} -gt $max ] &&max=${rand[$i]}
done
echo "max is$max"
2)定义一个数组,数组中元素是/var/log目录下所有以.log结尾的文件,统计其下标为偶数的文件中的行数之和
#!/bin/sh
declare -a files
files=(/var/log/*.log)
declare -i lines=0
for a in $(seq 0$[${#files[*]}-1]);do
if [ $[$a%2] -eq 0 ];then
let lines+=$(wc -l ${files[$a]} |cut -d ' ' -f1)
fi
done
echo"lines:$lines"
3、变量字符串的操作
(1)获取长度
echo ${#variable}
echo $variable | wc –l
[[email protected] ~]#DAYI="i am dayi123"
[[email protected] ~]# echo${#DAYI}
12
[[email protected] ~]# echo$DAYI | wc -L
12
(2)截取字符串子串
echo ${variable:n} #从第n个字符开始截取
echo ${variable:n:m} #从第n个字符串始截取m个字符
echo $variable | cut –c n-m #从第n个字符开始截取m个字符
[[email protected] ~]# echo${DAYI:2}
am dayi123
[[email protected] ~]# echo${DAYI:2:5}
am da
[[email protected] ~]# echo$DAYI | cut -c 2-5
am
(3)替换操作
echo ${variable/char1/char2} #将字符串中的char1替换为char2,只替换第一个
echo ${variable//char1/char2} #将变量中的所有字符串char1替换为char2
[[email protected] ~]#DAYI="dayi123DAYIdayi"
[[email protected] ~]# echo${DAYI/dayi/liu} #将第一个dayi替换为liu
liu123DAYIdayi
[[email protected] ~]# echo${DAYI//dayi/liu} #替换所有的dayi为liu
liu123DAYIliu
(4)删除操作
echo ${variable#char1} #从头开始删除匹配到的char1
echo ${variable#a*c} #删除第一次匹配到的a*c之间的内容
echo ${variable##a*c} #删除匹配到最长的a*c之间的内容
echo ${variable%a*c} #从结尾开始删除匹配到最短的a*c之间的内容
echo ${variable%%a*c} #从结尾开始删除匹配到最长的a*c之间的内容
[[email protected] ~]# echo$DAYI
dayi123DAYIdayi
[[email protected] ~]# echo${DAYI#dayi} #删除第一个匹配到的dayi
123DAYIdayi
[[email protected] ~]# echo${DAYI#d*i} #删除匹配到的d*i之间的内容
123DAYIdayi
[[email protected] ~]# echo${DAYI##d*i} #删除匹配到的最长的d*i之间的内容
[[email protected] ~]# echo${DAYI%d*i} #删除从结尾匹配到的d*i之间的内容
dayi123DAYI
[[email protected] ~]# echo${DAYI%%d*i} #删除从结尾匹配到的最长的d*i的内容
[[email protected] ~]# echo${DAYI%%dayi} #删除从结尾匹配到的dayi
dayi123DAYI
(5)字符的大小写替换
echo ${variable^^} #将变量中的小写字符替换为大写
echo ${variable,,} #将变量中的大写字符替换为小写
[[email protected] ~]# echo${DAYI^^}
DAYI123DAYIDAYI
[[email protected] ~]# echo${DAYI,,}
dayi123dayidayi
(6)变量的测试
${variable:-char} #如果变量存在且非空,则返回变量的值,否则返回char
${variable:=char} #如果变量名存在且非空,则返回变量值,否则设置variable的值为char,并返回其值
${variable:+char} #如果变量存在则返回CHAR,否则返回空值
[[email protected] ~]# echo${DAYI:=HELLO} #变量DAYI存在,所以返回变量DAYI的值
dayi123DAYIdayi
[[email protected] ~]# echo${LIU:=HELLO} #变量LIU不存在,所以返回HELLO,并赋值给LIU
HELLO
[[email protected] ~]# echo$LIU
HELLO
[[email protected] ~]# echo${DAYI:-HELLO} #变量DAYI存在,返回DAYI的值
dayi123DAYIdayi
[[email protected] ~]# echo${YI:-HELLO} #变量YI不存在,所以返回HELLO,但并没有赋值
HELLO
[[email protected] ~]# echo$YI
[[email protected] ~]# echo${DAYI:+HELLO} #变量DAYI存在,所以返回HELLO
HELLO
[[email protected] ~]# echo${hehe:+HELLO} #变量hehe不存在,所以返回空
[[email protected] ~]#
4、补充一些小命令
(1)创建临时文件和目录
用法:mktemp filename.XXXX 创建并系那是临时文件
选项:-d 创建临时目录
注:X必须为大写,而且数量不小于三
[[email protected] script]#mktemp /tmp/dayi.XXXX
/tmp/dayi.dA5h
[[email protected] script]#mktemp -d /tmp/dayi123.XXXX
/tmp/dayi123.jkIq
(2)install命令
作用:复制文件并设置属性
用法:install [选项] sourcefile dfile
选项:-m 指定权限,默认755
-o 指定属主身份
-g 指定属组身份
-d 创建空目录
[[email protected] script]#install -m 755 -o dayi123 -g dayi123 trap.sh trap1.sh [[email protected] script]# lltrap1.sh
-rwxr-xr-x. 1 dayi123dayi123 242 Apr 10 21:29 trap1.sh
5、捕捉信号trap
(1)作用:用于指定在接受到信号后将要采取的动作,常见的用途是在脚本程序被中断时完成清理工作
(2)用法:
1)trap '触发指令' 信号
自定义进程收到系统发出的指定信号后,将执行触发指令,而不会执行原操作
2)trap '' 信号
忽略信号的操作
3)trap '-' 信号
恢复原信号的操作
4)trap -p
列出自定义信号操作
(3)案例:
案例1:当按下ctrl+c时终止ping,捕捉信号并进行操作
#!/bin/sh
trap 'echo"stop"' INT
ping 172.16.0.1
案例2:测试一个网段的主机,当按下ctrl+c时中断测试
#!/bin/sh
trap 'echo"stop";exit 1' INT
for(( i=1;i<=254;i++))
do
ping 172.16.0.$i
done
案例三:通过函数实现,测试指定网段的主机是否在线,并为每台主机生成临时文件存储主机状态。测试完成后,删除临时文件。
#!/bin/sh
declare -a hosttmpfiles
trap 'mytrap' INT
mytrap(){
echo "QUIT"
rm -f ${hosttmpfiles[@]}
exit 1
}
for((i=1;i<=10;i++))
do
tmpfiles=$(mktemp /tmp/ping.XXXXXX)
if ping -W 1 -c 1 172.16.0.$i&>/dev/null;then
echo "172.16.0.$i is up " |tee $tmpfiles
else
echo "172.16.0.$i is down" |tee $tmpfiles
fi
hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfiles
done
mytrap
6、窗口化编程dialog
(1)作用:提供窗体,但输入完成后,默认将数据输出到错误输出,而不是标准输出(需要安装dialog包)
(2)操作:
让用户选择:dialog –backtitle“firest test” –-title “create user” –yesno ‘hostname’ 10 30
让用户输入:dialog –backtitle “firest test” –title “create user” –inputbox‘hostname’ 10 30
接受用户的选择并赋值给变量:dialog --stdout –backtitle ‘ADD USER’ –title “username” –inputbox “username”10 30
(3)利用窗口化编程创建用户:
#!/bin/sh
while true
do
username=`dialog--stdout --backtitle 'add user' --title 'username' --inputbox "pleaseinput a username:" 20 40`
retval=$?
if [ $retval -ne 0 -o"$username" == "exit" -o -z "$username" ]
then
exit
elif [ $retval -eq 0 -a-n "$username" ]
then
if ! id $username &>/devl/null;
then
useradd $username
pass=`dialog --stdout --backtitle 'adduser' --title 'password' --inputbox "please input password:" 20 40`
echo $pass | passwd --stdin $username
dialog --backtitle 'add user' --title'title' --msgbox "add user $username successful" 10 20
else
dialog --backtitle 'add user' --title'add user' --msgbox "$username is already create" 10 20
fi
fi
done
转载于:https://blog.51cto.com/dayi123/1927621