脚本之循环的特殊用法及函数的使用

一、本文主要时针对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

(1)
NarutoNaruto
上一篇 2016-08-21
下一篇 2016-08-21

相关推荐

  • LVS模型练习

    本次涉及到的练习:nat练习、dr练习、FWM机制练习、mysql集群练习、httpd的集群练习、httpd和mysql结合调度的练习 yum install ipvsadm nat练习     设置:     (1)centos7.2作为lvs调度,有两块网卡,(公网地址)其中…

    Linux干货 2016-10-30
  • N25-第一周博客作业

    计算机的组成及其功能 Linux的发行版介绍 Linux的哲学思想 Linux命令格式及一些基础命令 在Linux系统上获取命令的帮助信息 Linux发行版的基础目录 计算机的组成及其功能 简单来说,计算机系统是由 硬件系统(hardware system)和 软件系统(software system)两部分组成。 硬件的基本组成: 运算器、存储器、控制器、…

    Linux干货 2016-12-02
  • Linux GNU AWK使用

                                    Linux GNU AWK使用 本章内容: awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 awk条件判断…

    系统运维 2016-10-01
  • 8月3号 用户权限作业

     1,当用户xiaoming 对/testdir  目录无执行权限时,意味着无法做哪些操作?   先创建目录/testdir,接着修改目录的/testdir的权限,用xiaoming的身份去进入/testdir目录 [root@localhost ~]# mkdir /testdir [root@l…

    Linux干货 2016-08-08
  • linux基础2

    linux基础2

    Linux干货 2018-03-18
  • 计算机的组成及Linux简单介绍

    马哥教育网络班22期第一周练习 计算机概述 进入计算机的世界 计算机 计算机(computer)俗称电脑,是能够按照程序运行,自动、高速出炉海量数据的现代化智能电子设备。由硬件系统和软件系统所组成,计算机的组成遵循冯诺依曼体系。可分为超级计算机、工业控制计算机、网络计算机、个人计算机和嵌入式计算机等五类,较先进的计算机有生物计算机、光子计算机、量子计算机等。…

    Linux干货 2016-08-14