Bash编程之循环&函数

简介:
1
2
3
4
5
6
7
8
Bash编程之循环&函数
一、bash循环( for , while ,until)
二、测试脚本
三、多分支 if
四、 case 语句的语法格式
五、function函数
六、变量作用域
七、函数递归

一、bash循环(for,while,until)

1.bash脚本编程
    顺序执行
    选择执行
    循环执行
        for,while,until,
        
    进入条件:
        for :列表元素非空
        while :条件测试结果为“真”
        until:条件测试结果为“假”
    退出条件:
        for:列表元素为空
        while:条件测试结果为“假”
        until:条件测试结果为“真”
2.循环控制语句:
        while CONDATION1 ; do
            CMD1
            ...
            if CONDATION2;then
                continue //结束本次循环
            fi
                CMDn
                ...
        done
        示例:求100以内所有偶数之和
3.创建循环体;
        while true ;do
            循环体
        done
        退出方式:某个测试条件满足时,让循环体执行break命令
        
    break:直接跳出循环
    continue:直接进入下一次循环
    sleep 数字[时间单位] //默认是s,d:天,h:小时 
    
4.while循环的特殊用法(遍历文件的行)
        while read VAR; don
            循环体
        done < /path/to/somefile
        依次读取/path/from/somefile文件中的每一行,且将某赋值给VAR变量
        
        示例:脚本5
5.for循环的特殊用法
    for ((控制变量初始化;条件判断表达式;控制var的修正语句))
        循环体
    done
    控制变量初始化,仅在循环代码开始运行时执行一次
    控制变量的修正语句;每轮循环结束会先进行控制变量修正运算,而后在根据判断条件判断
    
    
二、测试脚本    
脚本1:求even:偶数,odd:奇数,100以内之和

1
2
3
4
5
6
7
8
9
10
11
12
     #!/bin/bash
     declare -i evensum=0 /
     declare -i i=0
     while  [ $i -le 100 ] ;  do
             let  i++            //前面不能用let $i++
             if   [  $[$i%2] -eq 0 ] ;then   //此处只能使用[ ] 进行引用
                     let  evensum+=$i
             else
                     continue
             fi
     done
     echo  "Even sum is $evensum"

    //求所有奇数之和2500    

1
2
3
4
5
6
7
8
9
10
11
12
13
     #!/bin/bash
     declare -i evensum=0
     declare -i i=0
     
     while  [ $i -lt 100 ] ;  do     //必须是小于100,否则会出错
         let  i++
         if   [  $[$i%2] -eq 1 ] ;then
             let  evensum+=$i
         else 
             continue 
         fi
     done
     echo  "Even sum is $evensum"

脚本2:求和,break方式实现

1
2
3
4
5
6
7
8
9
10
11
     #!/bin/bashk
     declare -i oddsum=0
     declare -i i=1
     while  true do
         let  oddsum+=$i
         let  i+=2
         if  [ $i -gt 100 ];then
             echo $oddsum
             break
         fi
     done

脚本3:每个三s获取已经登录的用户信息,如果wolf用户已经登录,则记录于日志中,并退出

1
2
3
4
5
6
7
8
     #!/bin/bash
     while  true do
         if  who |grep wolf &> /dev/ null  ; then
             break
         fi
             sleep 3
     done
     echo  "$(date +%F-%H-%M) wolf loggin..."  >> /tmp/userlog.log

    
脚本4:util实现脚本3

1
2
3
4
5
     #!/bin/bash
     until who | grep  "wolf"  &> /dev/ null  do
         sleep 3
     done
     echo  "$(date +%F-%H-%M) wolf loggin..."  >> /tmp/userlog.log

    
脚本5:当前os上id号为偶数的用户及其shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
     #!/bin/bash
     declare -i userid
     while  read i ; do
             userid=`echo $i | cut -d: -f3`
                 //注:同上userid=$(echo $i | cut -d: -f3)
             if  [ $[$userid%2] -eq 0 ] ;then
                     echo $i | cut -d: -f1,7
             fi
     done < /etc/passwd
     //另一种实现方式,while循环                      
     #!/bin/bash
     declare -i userid
     while  read i ; do
         userid=$(echo $i | cut -d: -f3)
         username=$(echo $i | cut -d: -f1)
         usershell=$(echo $i | cut -d: -f7)
         if  [ $[$userid%2] -eq 0 ] ;then
             echo  "$username $userid $usershell"
         fi
      done < /etc/passwd


    
脚本6:for的特殊用法

1
2
3
4
5
6
     #!/bin/bash
     declare -i sum=0
     for  ((i=1;i<=100;i++)); do
             let  sum+=$i
     done
     echo  "Sum: is .$sum"

脚本7;使用for的特殊用法,打印99表

1
2
3
4
5
6
7
8
     #!/bin/bash
     #
     for  ((i=1;i<=9;i++)); do
         for  ((j=1;j<=i;j++)); do
             echo -e -n  "${i}*${j}=$[$i*$j]\t"
         done
         echo   //这个echo用于换行,因为前面不换行了
     done

三、多分支if
多分支if
    if condation1;then
        ..
    elif
        ...
    else
        ...
    fi
    单分支if
示例1:显示一个菜单给用户
    要求:
        1.提示用户给出自己的选择
        2.正确的选择,则给出相应的信息,否则提示,用户重新选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
     #!/bin/bash
     cat << EOF
     cpu) display cpu information
     mem) display memory information
     disk) display disks information
     quit) quit
     ===============================
     EOF
     read -p  "Enter your choice: "  opt
     while  "$opt"  !=  "cpu"  -a  "$opt"  !=  "mem"  -a  "$opt"  !=  "disk"  -a  "$opt"  !=  "disk"  -a "$
     opt " != " quit " ] ;do    read -p " Enter your choice: " opt
     done
     if  "$opt"  ==  "cpu"  ] ;then
         lscpu
     elif [  "$opt"  ==  "mem"  ] ;then
         free -m
     elif [  "$opt"  ==  "disk"  ] ;then
         fdisk -l /dev/sd[a-z]     
     else
         echo  "quit"
         exit 0
     fi

四、case语句的语法格式
    case $VAR in  //仅仅支持glob风格的通配符
    PAT1)
        ...
        ;; //双分号结尾
    PAT2)
        ...
        ;; //
    ...
    *)
        ...
        ;;
    esac
    
    注意:    
        case支持glob风格的通配符
            *:任意长度的任意字符
            ?:任意单个字符
            []:范围内的
            a|b :a或者b
case实现示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
     #!/bin/bash
     cat << EOF
     cpu) display cpu information
     mem) display memory information
     disk) display disks information
     quit) quit
     ===============================
     EOF
     read -p  "Enter your choice: "  opt
     while  "$opt"  !=  "cpu"  -a  "$opt"  !=  "mem"  -a  "$opt"  !=  "disk"  -a  "$opt"  !=  "disk"  -a "$
     opt " != " quit " ] ;do    read -p " Enter your choice: " opt
     done
     
     case  $opt  in 
     cpu)         //不用加“ ”
         lscpu
         ;;         //最后要加 ;;
     disk)
         fdisk -l /dev/sd[a-z]
         ;;
     mem)
         free -m
         ;;
     *)
         echo  "quit"
         exit 0     ;;
     esac

五、function函数
    过程式编程:代码重用
        模块化编程
        结构化编程
    把一段独立功能的代码当做一个整体,并为之一个名字;命名的代码段,此即为函数    
    注意:定义函数的代码段不会自动执行,在调用时执行,所谓调用函数,在代码中给定函数名即可
        函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码
    语法一:
        function f_name () { //function和f_name之间有空格
            ...函数体...            
        }
    语法二:
        f_name() {  //f_name() 中间没有空格
            ...函数体...
        }
    函数的生命周期:每次被调用时,返回时终止
        其状态返回结果:函数体中运行的最后一条命令的状态结果;
        自定义状态返回值:需要使用:return
            return [0-255] 
                0:成功
                1-255:失败
        脚本使用:exit #作为其返回值
    示例:脚本4
    
    注意:在函数中,不能使用$1,$2,...因为具有特殊的意义
        因为函数也可以接受参数,
            $1,$2调用的是,传递给函数的参数,而不是脚本的参数
    
    函数返回值
        函数的执行结果返回值;
        (1)使用echo或printf命令进行输出
            printf不会自动换行,相当于echo -n
        (2)函数体中调用的命令的执行结果
            函数的退出状态码
            1.默认取决于函数最后执行的那一条命令
            2.自定义的方法,return
    函数可以接受参数
        传递参数给函数
            1.在函数体中,可以使用$1,$2,...引用传递给函数的参数;
                $*和$@调用所有参数,
                $#引用参数个数
            2.在调用函数时,在函数名后以空白字符分隔给定参数列表即可,例如:a b c d
            
六、变量作用域
    局部变量:作用域是函数的声明周期
        定义:locale VARIABLE=VALUE
    本地变量:作用域是运行脚本的shell的生命周期;作用范围是当前shell程序
        a=VALUE //
    全局变量:
    环境变量:
    
    全局变量和局部变量对比:

1
2
3
4
5
6
7
8
9
10
11
         #!/bin/bash
         name=tom
         setname() {
             local name=jerry
             echo  "Function name:$name"
         }
         setname
         echo  "Shell: $name"
     [root@localhost ~]# bash 2.sh
     Function name:jerry
     Shell: tom

    
七、函数递归 //自己调用自己
    函数间接或者直接就调用自身
    10!=10*9!=10*9*8!=...
    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
fact() {
     if  [ $1 -eq 0 -o $1 -eq 1 ] ;then  //[ $1 -eq 0 ] || [ $1 -eq 1 ] 这样也可以
         echo $1
     else
         echo $[$1*$(fact $[$1-1])]
     fi
}
fact $1
#!/bin/bash
fab() {
     if  [ $1 -eq 1 ] ;then
         echo -n  "1 "
     elif [ $1 -eq 2 ] ;then
         echo -n   "1 "
     else
         echo -n  "$[$(fab $[$1-1]+$(fab $[$1-2])]"
         fi
}        
for  in  $(seq 1 $1) ; do
     fab $i
done
echo

服务启动服务框架
    $lockfile,值/var/lock/subsys/SCRIPT_NAME
    1.可以接受的参数start,stop,restart,status四个参数
    2.如果参数非此四个,则显示帮助后退出
    3.start,创建lockfile,并显示启动:stop,则创建lockfile,并显示停止;restart,则先删除此文件,再创建此文件,而后显示重启完成,;
        statue根据lockfile是否存在,显示running/stopped
    注:务必使用case语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/bash
#
# chkconfig: - 50 50
# description test_service_script
prog=$(basename $0)
lockfile=/ var / lock /subsys/$prog
case  $1  in
start)
     if  [ -f $lockfile ] ;then
         echo  "$prog is running yet."
     else
         touch $lockfile 
         [ $? -eq 0 ] && echo  "Start $prog finished.."
     fi
     ;;
stop)
     if  [ -f $lockfile ] ;then
         rm -f $lockfile
         [ $? -eq 0 ] && echo  "$prog stopped.."
     else
         echo  "$prog is not running.."
     fi
     ;;
restart)
     if  [ -f $lockfile ] ; then    
         rm -f $lockfile
         touch $lockfile
         echo  "$prog restart finished.."
     else
         touch $lockfile
         echo  "$prog start finished.."
     fi
     ;;
status)
     if  [ -f $lockfile ] ;then
         echo  "$prog is running.."
     else
         echo  "$prog is stopped.."    
     fi
     ;;
*)
     echo  "Usage: $prog {start|stop|resatrt|status}"
esac                    
     
     cp service /etc/init.d/service
     chmod +w /etc/init.d/service
     chkconfig --add service
     service service start

    
八、function脚本
1.给定一个用户名,获取其id和shell

1
2
3
4
5
6
7
8
9
10
11
12
13
     #!/bin/bash
     #
     userinfo() {
         if  id  "$username"  &> /dev/ null  ;then    
             grep  "$username"  /etc/passwd | cut -d: -f3,7
         else
             echo  "No $username such user.."
         fi
     }
     username=$1
     userinfo          //调用该函数,可以调用多次
     username=$2
     userinfo

2.升级版    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
     #!/bin/bash
     #
     # chkconfig: - 50 50
     # description test_service_script
     prog=$(basename $0)
     lockfile=/ var / lock /subsys/$prog
     start() {
         if  [ -f $lockfile ] ;then
             echo  "$prog is running yet."
         else
             touch $lockfile 
             [ $? -eq 0 ] && echo  "Start $prog finished.."
         fi
     }
     stop() {
         if  [ -f $lockfile ] ;then
             rm -f $lockfile
             [ $? -eq 0 ] && echo  "$prog stopped.."
         else
             echo  "$prog is not running.."
         fi
     }
     restart() {
         if  [ -f $lockfile ] ; then    
             rm -f $lockfile
             touch $lockfile
             echo  "$prog restart finished.."
         else
             touch $lockfile
             echo  "$prog start finished.."
         fi
     }
     status() {
         if  [ -f $lockfile ] ;then
             echo  "$prog is running.."
         else
             echo  "$prog is stopped.."    
         fi
     }
     usage() {
         echo  "Usage: $prog {start|stop|resatrt|status}"
     }
     
     case  $1  in 
     start)
         start ;;
     stop)
         stop ;;
     restart)
         restart;;
     status)
         status;;
     *)
         usage;;
     esac

    
3.添加10个用户
    添加用户的功能用函数实现,用户名作为参数传递给函数    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
#
# 5: user is exists
#
#
adduser() {
     if  id $1 &> /dev/ null ; then
         return  5
     else
         useradd $1
         retval=$?
         return  $retval  
     fi
}
for  in  {1..10} ; do
         adduser ${1}$i 
         a=$?   //$?不要直接引用,如果需要多次引用的话,进行赋值变量
     if  [ $a -eq 0 ] ;then
          echo  "useradd succeed..."
     elif [ $a -eq 5 ] ;then
          echo  "user ${1}$i is exists ,useradd failure."
     else
          echo  "Unknown errors.." 
     fi
done














本文转自MT_IT51CTO博客,原文链接:http://blog.51cto.com/hmtk520/1979188 ,如需转载请自行联系原作者
相关文章
|
存储 Shell 索引
如何在Bash中使用For循环和数组?
如何在Bash中使用For循环和数组?
450 0
|
5月前
|
Shell 开发者
深入理解Bash脚本中的函数
【8月更文挑战第20天】
100 0
|
5月前
|
监控 安全 Shell
有用的 Bash 别名和函数简介
有用的 Bash 别名和函数简介
28 0
|
8月前
|
存储 弹性计算 运维
bash中的函数
【4月更文挑战第29天】
41 0
|
8月前
|
Shell
在Shell(如Bash)中,`while`循环
在Shell(如Bash)中,`while`循环
117 2
|
8月前
|
机器学习/深度学习 Unix Shell
Shell编程基础入门(Bash|变量与输入输出重定向2&1)
Shell编程基础入门(Bash|变量与输入输出重定向2&1)
136 0
|
Java Shell Linux
如何在 Linux 中使用 Bash For 循环
如何在 Linux 中使用 Bash For 循环
183 0
|
缓存 Shell 开发工具
【Shell编程】Shell中Bash基本功能
【Shell编程】Shell中Bash基本功能
107 0
【Shell编程】Shell中Bash基本功能
|
Shell
【Shell编程】Shell中Bash变量-数值运算、运算符变量、测试和内容替换
【Shell编程】Shell中Bash变量-数值运算、运算符变量、测试和内容替换
99 0
|
Shell
【Shell编程】Shell中Bash变量-预定义变量
【Shell编程】Shell中Bash变量-预定义变量
119 0