一、本文主要时针对while for select循环结果的特殊用法进行讲解。
1、while循环的特殊用法
while read line ;do
循环体
done < /path/from/somefile
功能:依次从输入重定向的文件中读取每一行的内容复制给变量line,然后我们可以在循环体中执行对$line的操作,
应用举例:扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功
#!/bin/bash # while read line do zhushi=`echo $line | cut -d: -f5` userName=`echo $line | cut -d: -f1` if [[ -z $zhushi ]];then chfn -f $userName $userName &> /dev/null chfn -p 62985600 $userName &> /dev/null echo "$userName :信息修改成功" fi done < /testdir/passwd
2、for循环的特殊用法
for ((i=1;i<100;i++))
do
循环体
done
注意:此处for循环的使用类似与c语言的语法,但是不同的是此处需要的是双括号。
3、select循环的特殊用法
select 变量 in 参数…
do
循环体命令
done
功能:将多个参数依次付给变量,并在屏幕上依次按照编号从1-n把参数显示出来,并根据选择的编号,来选择指定的参数,通常我们配合case 变量 in 来使用,因为select 是个死循环,因此需要借助break或者exit退出循环体,且可以省略in 参数,此时使用位置参数,PS3 可以定义选择提示符,用户输入编号被保存在内置变量REPLY中。
应用举例:可以参照下面服务脚本/root/bin/testsrv.sh
二、函数的用法
函数也由多条命令堆积组合在一起组成,我们可以将一些简单的,需要重复使用的命令组合起来写成函数,然后直接调用即可,这样避免了,我们重复编写代码,可提高效率。
脚本也是有多个命令堆积组合而成,那么他们有什么区别呢?当我们在一个脚本中调用一个脚本时,我们相当于又重新开启了一个子shell,当我们定义一个函数并调用该函数时,相当于之当前shell中运行的,在当前shell中定义的变量,可以在函数中调用和访问的,且函数不能独立运行,必须调用时才能执行,在函数中定义变量最好定义局部变量,避免与脚本中的命令相同的本地变量发生冲突。
定义函数:
语法1:
function f_name {
…函数体…
}
语法2:
f_name() {
…函数体…
}
定义一个函数,在一个文件中定义一个文件不一定必须时.sh结尾的 只要是文本文件即可,然后写一个脚本,然后调用该函数
函数的定义和使用:
可以在交互环境下定义函数
可以将函数放在脚本中作为它的一部分,直接调用函数名,即可执行函数内部的代码
可放在只包含函数的单独文件中,通过source filename 就可以将函数读到指定的shell中,便于后续我们调用一些功能模块
函数的生命周期:被调用时创建,返回时终止
函数有两种返回值:
使用echo或printf命令的输出结果
函数体中调用命令的输出结果
函数的退出状态码:
默认取决于函数中执行的最后一条命令的退出状态码
自定义退出状态码,其格式:
return 从函数中返回,用最后状态命令决定返回值
return 0 无错返回
return 1-255 有错返回
—-等同于脚本中的break功能
当我们在命令行中定义了一个命令时,可以通过set命令查看该函数,也可通过unset 函数名 取消该函数。
在脚本中定义函数时,必须要在引用脚本之前定义函数,否则会由于查找不到函数体,而报错。
函数也可以接受位置变量
函数的递归:(自己调用自己)
函数直接或间接引用自身
应用举例:n!=n(n-1)(n-2)…1
#!/bin/bash # fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 #当$1=1时fun函数通过echo输出的结果 else echo $[$1*$(fact $[$1-1])] fi } fact 5 每次输出调用函数fact 知道等$=1 才会有输出结果
1、写个脚本:
*
***
******
********
#!/bin/bash # read -p "please input the longs:" long for hang in `seq 1 $long`;do spaceNum=$[long-hang] xingNum=$[hang*2-1] for spacenum in `seq $spaceNum`;do echo -n " " done for xingnum in `seq $xingNum`;do echo -n "*" done echo done
root@cenots6.8 /testdir # ./jinzita.sh please input the longs:4 * *** ***** *******
2、用until循环实现国际象棋棋盘
declare -i hang=1 until [ $hang -gt 8 ];do lie=1 until [ $lie -gt 8 ];do z=$[lie%2] if [ $z -eq 0 ];then [[ $hang%2 -eq 0 ]] && echo -ne "\033[43m" "" "\033[0m" || echo -ne "\033[41m" "" "\033[0m" else [[ $hang%2 -eq 0 ]] && echo -ne "\033[41m" "" "\033[0m" || echo -ne "\033[43m" "" "\033[0m" fi let lie++ done echo let hang++ done
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为当前脚本名
#!/bin/bash # baseName=$(basename $0|cut -d"." -f1) fileName=/var/lock/subsys$baseName PS3="请输入您要选择的编号:" select menu in start stop restart status do case $menu in start) if [ -f $fileName ];then echo "功能已经启动,如需重新启动,请选择 restart " else touch $fileName echo "启动成功" fi ;; stop) if [ -f $fileName ];then rm -rf $fileName echo "停止完成" else echo "该功能已经停止,无需再次停止" fi ;; restart) rm -rf $fileName echo "停止完成" touch $fileName echo "启动成功" ;; status) [ -f $fileName ] && echo "$baseName is running..." || echo "$baseName is stoped..." ;; *) echo "您输入的信息有误" exit 1 ;; esac done
root@cenots6.8 /testdir # ./testsrv.sh 1) start 2) stop 3) restart 4) status 请输入您要选择的编号:1 启动成功 请输入您要选择的编号:1 功能已经启动,如需重新启动,请选择 restart 请输入您要选择的编号:2 停止完成 请输入您要选择的编号:2 该功能已经停止,无需再次停止 请输入您要选择的编号:3 停止完成 启动成功 请输入您要选择的编号:4 testsrv is running... 请输入您要选择的编号: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/ld
linux-x86-64.so.2
(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命
令,并重复完成上述功能;直到用户输入quit退出
#!/bin/bash read -p "请输入一个可执行的命令:" Cmd [ -z $Cmd ] && echo "输入信息不能为空" && exit 1 destDir=/mnt/sysroot [ -d $destDir ] || mkdir $destDir while [[ $Cmd != quit ]]; do cmdDir=`which $Cmd` #取得命令二进制路径 libDir=$(ldd `which cat` | sed -n "3p"|tr -d [[:space:]] | sed -r 's@(^/.*)\(.*\)$@\1@g') #取得库文件的路径 cmddirName=`dirname $destDir$cmdDir` #取得命令的路径名 mkdir -p $cmddirName #创建目录 cp -r $cmdDir $destDir$cmdDir #复制二进制文件到目标目录中 echo "复制$destDir$cmdDir 完成" libdirName=`dirname $destDir$libDir` mkdir -p $libdirName cp -r $libDir $destDir$libDir echo "复制$destDir$libDir 完成" read -p "请重新输入新的要复制的命令:" Cmd [ -z $Cmd ] && echo "输入信息不能为空" && exit 1 done
root@cenots6.8 /testdir # ./copycmd.sh 请输入一个可执行的命令:cut 复制/mnt/sysroot/bin/cut 完成 复制/mnt/sysroot/lib64/ld-linux-x86-64.so.2 完成 请重新输入新的要复制的命令:getent 复制/mnt/sysroot/usr/bin/getent 完成 复制/mnt/sysroot/lib64/ld-linux-x86-64.so.2 完成 请重新输入新的要复制的命令:quit root@cenots6.8 /testdir # root@cenots6.8 /testdir # /mnt/sysroot/bin/c cat cut root@cenots6.8 /testdir # /mnt/sysroot/bin/c cat cut root@cenots6.8 /testdir # /mnt/sysroot/bin/cut -d":" -f1 /etc/passwd root bin daemon
3、写一个函数实现两个数字做为参数,返回最大值
#!/bin/bash # function max(){ [ $1 -lt $2 ] && max=$2 && echo "最大值为:$2" } max $1 $2
root@cenots6.8 /testdir # ./fun3.sh 1 3 最大值为:3
4、写一个函数实现数字的加减乘除运算,例如输入 1 + 2,将得出正确结果
#!/bin/bash # function jia(){ let Sum=$1+$2 echo "和为:$Sum" } function jian(){ let Cha=$1-$2 echo "差为:$Cha" } function cheng(){ let Ji=$1*$2 echo "乘积为:$Ji" } function chu(){ let Shang=$1/$2 echo "商为:$Shang" }
#!/bin/bash source testfun.sh jia $1 $2 jian $1 $2 cheng $1 $2 chu $1 $2
root@cenots6.8 /testdir # ./testfuns.sh 9 3 和为:12 差为:6 乘积为:27 商为:3
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阶斐波那契数列
#!/bin/bash # function feibonaqie() { if [ $1 -eq 0 ];then echo 0 elif [ $1 -eq 1 ];then echo 1 else echo $[$1+`feibonaqie $[$1-1]`+`feibonaqie $[$-2]`] fi } feibonaqie $1
root@cenots6.8 /testdir # ./feibonaqie.sh 3 6
6、汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。利用函数,实现
原创文章,作者:Naruto,如若转载,请注明出处:http://www.178linux.com/38199