描述:
select控制语句基于Korn Shell中的控制结构
select语句首先显示一个菜单,然后根据用户的选择给变量赋予相应的值,最后执行一系列命令。
语法:
select varname [ in arg…]
do
commands
done
说明:
select结构显示arg项的菜单。加入忽略关键字in和参数列表,select控制语句就用位置参数来取代arg项。select的菜单格式化为在每一项前加一个数字。
select循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准输出上,并显示PS3提示符,等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令。
用户输入被保存在内置变量REPLY中。
select是个无限循环,使用break命令退出循环,或用exit命令终止脚本,也可以按ctrl+c推出循环
select经常和case联合使用
与for循环类似,可以省略in list,此时使用位置参数
示例:
#!/bin/bash PS3="Please guss which fruit I like:" select var in "apple" "pear" "orange" "peach";do if [ "$var" == "apple" ];then echo "You are right" break else echo "try again" fi done [root@localhost ~]# bash a.sh 1) apple 2) pear 3) orange 4) peach Please guss which fruit I like:2 try again Please guss which fruit I like:3 try again Please guss which fruit I like:4 try again Please guss which fruit I like:1 You are right
函数:
函数(function)是由若干条shell命令组成的语句块,实现代码重用和模块化编程,
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
函数和shell程序的区别在于:
shell程序在子shell中运行,而shell函数在当前shell中运行。因此在当前shell中,函数可以对shell中的变量进行修改
函数由两部分组成:函数名和函数体
语法一:
function NAME {
函数体
}
语法二:
NAME() {
函数体
}
函数的使用:
可以在交互式环境下定义函数
可将函数放在脚本文件中作为它的一部分
可放在只包含函数的单独文件中
调用:函数只有被调用才会执行
调用:给定函数名
函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止
函数的执行结果返回值:
1,使用echo或printf命令进行输出
2,函数体调用命令的输出结果
函数的退出状态码:
1,默认取决于函数最后一条命令的退出状态码
2,自定义退出状态码,其格式为:
return 从函数中返回,用最后状态命令决定返回值
return 0 正确返回
return 1-255 有错误返回
交互式环境下定义和使用函数
示例:
[root@localhost ~]# dir(){ > ls -l 定义该函数后,在命令行直接键入dir,其显示结果同ls -l的作用相同 > } [root@localhost ~]# dir -rw-r--r--. 1 root root 205 Aug 19 17:55 a.sh -rwxr-xr-x. 1 root root 106 Aug 12 05:42 backup.sh drwxr-xr-x. 2 root root 4096 Aug 15 06:28 bin [root@localhost ~]# unset dir 从当前系统中退出该dir函数
在脚本中定义及使用函数
函数在使用前必须定义,因此应该将函数定义放在脚本开始部分,直到shell首次发现它后才能使用
调用函数仅使用其函数名即可
示例:
[root@localhost ~]# cat func1 #!/bin/bash #func1 hello(){ echo "Hello there today's date is `date +%F`" } echo "now going to the function hello" hello echo "back from the function" [root@localhost ~]# chmod +x func1 [root@localhost ~]# ./func1 now going to the function hello Hello there today's date is 2016-08-21 back from the function
使用函数文件
可以将经常使用的函数存入函数文件,然后将函数文件载入shell
文件名可任意取,但最后与相关任务有某种联系。例如:functions.main
一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数
若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件
创建函数文件:
示例:
[root@localhost ~]# cat function.main 函数文件 #!/bin/bash #functions.main findit() { if [ $# -lt 1 ];then echo "Usage:findit file" return 1 fi find / -name $1 -print }
函数文件已创建好后,要将它载入shell
定位函数文件并载入shell格式:
. filename 或 source filename (即<点> <空格> <文件名>) (这里的文件名要带正确路径)
使用set命令检查函数是否已载入。set命令将在shell中显示所有已载入的函数
[root@localhost ~]# . function.main [root@localhost ~]# set findit () { if [ $# -lt 1 ]; then echo "Usage:findit file"; return 1; fi; find / -name $1 -print } [root@localhost ~]# findit groups 执行shell函数,键入函数名即可 /usr/bin/groups
[root@localhost ~]# unset findit 删除shell函数(命令格式为:unset function_name) [root@localhost ~]# set 函数findit无显示
函数参数:
传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;例如:"findit a b …"
在函数体中当中,可使用$1,$2,…调用参数,还可以使用$@,$*,$#等特殊变量
函数变量:
环境变量:当前shell和子shell有效
本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
局部变量:函数的生命周期;函数结束时变量被自动销毁
注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量
在函数中定义局部变量的方法: local NAME=VALUE
函数递归示例:
[root@localhost ~]# cat fact.sh #!/bin/bash fact() { if [ $1 -eq 0 -o $1 -eq 1 ];then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact 4 [root@localhost ~]# bash -x fact.sh + fact 4 + '[' 4 -eq 0 -o 4 -eq 1 ']' ++ fact 3 ++ '[' 3 -eq 0 -o 3 -eq 1 ']' +++ fact 2 +++ '[' 2 -eq 0 -o 2 -eq 1 ']' ++++ fact 1 ++++ '[' 1 -eq 0 -o 1 -eq 1 ']' ++++ echo 1 +++ echo 2 ++ echo 6 + echo 24 24
作业:
1、写一个服务脚本/root/bin/testsrv.sh,完成如下要求
(1) 脚本可接受参数: start, stop, restart, status
(2) 如果参数非此四者之一,提示使用格式后报错退出
(3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”
考虑:如果事先已经启动过一次,该如何处理?
(4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”
考虑:如果事先已然停止过了,该如何处理?
(5) 如是restart,则先stop, 再start
考虑:如果本来没有start,如何处理?
(6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示
“ SCRIPT_NAME is running…”
如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“ SCRIPT_NAME
is stopped…”
其中: SCRIPT_NAME为当前脚本名
[root@localhost function]# cat testsrv.sh #!/bin/bash fstart () { if [ -e "$1" ];then echo "Already Start" else touch $File echo "Start Successfully!" fi } fstop() { if [ -e "$1" ];then rm -f $File echo "Stop Successfully!" else echo "Already stop" fi } frestart() { if [ -e "$1" ];then fstop &> /dev/null fstart &> /dev/null echo "Restart Successfully!" else fstart &> /dev/null echo "Start Successfully!" fi } fstatus() { if [ -e "$1" ];then echo "testsrv is running" else echo "testsrv has been stop" fi } select choice in start stop restart status quit;do File=/var/lock/subsys/testsrv.sh case $choice in start) fstart $File ;; stop) fstop $File ;; restart) frestart $File ;; status) fstatus $File ;; quit) break ;; *) echo "error,please choose again" exit 2 esac done [root@localhost function]# bash testsrv.sh 1) start 2) stop 3) restart 4) status 5) quit #? 4 testsrv is running #? 3 Restart Successfully! #? 1 Already Start #? 2 Stop Successfully! #? 5
2、编写一个脚本/root/bin/copycmd.sh
(1) 提示用户输入一个可执行命令名称;
(2) 获取此命令所依赖到的所有库文件列表
(3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;
如: /bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:
如: /lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ldlinux-x86-64.so.2
(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命
令,并重复完成上述功能;直到用户输入quit退出
[root@localhost ~]# cat copycmd.sh #!/bin/bash ch_root="/mnt/sysroot/" [ ! -d $ch_root ] && mkdir $ch_root bincopy() { if which $1 &>/dev/null;then local cmd_path=`which --skip-alias $1` local bin_dir=`dirname $cmd_path` [ -d ${ch_root}${bin_dir} ] || mkdir -p ${ch_root}${bin_dir} [ -f ${ch_root}${cmd_path} ] || cp $cmd_path ${ch_root}${bin_dir} return 0 else echo "Command not found" return fi } libcopy() { local lib_list=$(ldd `which --skip-alias $1` | grep -Eo '/[^[:space:]]+') for loop in $lib_list;do local lib_dir=`dirname $loop` [ -d ${ch_root}${lib_dir} ] || mkdir -p ${ch_root}${lib_dir} [ -f ${ch_root}${loop} ] || cp $loop ${ch_root}${lib_dir} done } read -p "Please input a command:" command while [ "$command" != "quit" ];do if bincopy $command;then libcopy $command fi read -p "Please input a command or quit:" command done [root@localhost ~]# ll /mnt/sysroot/lib64 -rwxr-xr-x. 1 root root 164432 Aug 23 15:28 ld-linux-x86-64.so.2 -rwxr-xr-x. 1 root root 37056 Aug 23 15:28 libacl.so.1 -rwxr-xr-x. 1 root root 19888 Aug 23 15:28 libattr.so.1 -rwxr-xr-x. 1 root root 20024 Aug 23 15:28 libcap.so.2 -rwxr-xr-x. 1 root root 2107816 Aug 23 15:28 libc.so.6 -rwxr-xr-x. 1 root root 19512 Aug 23 15:28 libdl.so.2 -rwxr-xr-x. 1 root root 153192 Aug 23 15:28 liblzma.so.5 -rwxr-xr-x. 1 root root 398272 Aug 23 15:28 libpcre.so.1 -rwxr-xr-x. 1 root root 142296 Aug 23 15:28 libpthread.so.0 -rwxr-xr-x. 1 root root 147120 Aug 23 15:28 libselinux.so.1 [root@localhost ~]# ll /mnt/sysroot/usr/bin -rwxr-xr-x. 1 root root 54048 Aug 23 15:41 cat -rwxr-xr-x. 1 root root 117616 Aug 23 15:35 ls
3、写一个函数实现两个数字做为参数,返回最大值
#!/bin/bash function NUMBER { if [ $1 -lt $2 ];then echo "The max number is $2" elif [ $1 -eq $2 ];then echo "The two number is equal" else echo "The max number is $1" fi } NUMBER $1 $2
[root@localhost function]# bash test3.sh 3 5 The max number is 5 [root@localhost function]# bash test3.sh 6 4 The max number is 6 [root@localhost function]# bash test3.sh 8 8 The two number is equal
4、写一个函数实现数字的加减乘除运算,例如输入 1 + 2,将得出正确结果
[root@localhost function]# cat test4-1.sh #!/bin/bash fjia() { sum=$[$1+$2] echo "$sum" } fjian() { sum=$[$1-$2] echo "$sum" } fcheng() { sum=$[$1*$2] echo "$sum" } fchu() { sum=$[$1/$2] echo "$sum" } read -p "please input: " a b c case $b in +) fjia $a $c ;; -) fjian $a $c ;; \*) fcheng $a $c ;; /) fchu $a $c ;; *) echo "please input correct form" exit 3 esac [root@localhost function]# bash test4-1.sh please input: 6+7 please input correct form please input: 6 + 7 13 please input: 6 - 8 -2 please input: 2 * 3 6 please input: 4 / 2 2
5、斐波那契数列又称黄金分割数列,因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,斐波纳契数列以如下被以递归的方法定义: F( 0) =0, F( 1) =1, F( n) =F(n-1)+F(n-2)(n≥2)
写一个函数,求n阶斐波那契数列
[root@localhost function]# cat test5-1.sh #!/bin/bash ftzsl() { if [ $1 -eq 0 ];then echo "0" elif [ $1 -eq 1 ];then echo "1" else echo "$[$(ftzsl $[$1-1])+$(ftzsl $[$1-2])]" fi } read -p "please input a number: " n ftzsl $n [root@localhost function]# bash test5-1.sh please input a number: 5 5 please input a number: 6 8
6、汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间
一次只能移动一个圆盘。利用函数,实现N片盘的汉诺塔的移动步骤
[root@localhost function]# cat test6.sh #!/bin/bash fpan() { if [ $1 -eq 1 ];then echo "$2 ==> $4" else fpan $[$1-1] $2 $4 $3 echo "$2 ==> $4" fpan $[$1-1] $3 $2 $4 fi } fpan $1 a b c [root@localhost function]# bash test6.sh 2 a ==> b a ==> c b ==> c
原创文章,作者:pingsky,如若转载,请注明出处:http://www.178linux.com/38881