天天看点

Bash编程之循环&函数

<code>Bash编程之循环&amp;函数</code>

<code>一、bash循环(</code><code>for</code><code>,</code><code>while</code><code>,until)</code>

<code>二、测试脚本</code>

<code>三、多分支</code><code>if</code>

<code>四、</code><code>case</code><code>语句的语法格式</code>

<code>五、function函数</code>

<code>六、变量作用域</code>

<code>七、函数递归</code>

一、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

            循环体

        退出方式:某个测试条件满足时,让循环体执行break命令

    break:直接跳出循环

    continue:直接进入下一次循环

    sleep 数字[时间单位] //默认是s,d:天,h:小时 

4.while循环的特殊用法(遍历文件的行)

        while read VAR; don

        done &lt; /path/to/somefile

        依次读取/path/from/somefile文件中的每一行,且将某赋值给VAR变量

        示例:脚本5

5.for循环的特殊用法

    for ((控制变量初始化;条件判断表达式;控制var的修正语句))

        循环体

    done

    控制变量初始化,仅在循环代码开始运行时执行一次

    控制变量的修正语句;每轮循环结束会先进行控制变量修正运算,而后在根据判断条件判断

二、测试脚本    

脚本1:求even:偶数,odd:奇数,100以内之和

<code>    </code><code>#!/bin/bash</code>

<code>    </code><code>declare -i evensum=0 /</code>

<code>    </code><code>declare -i i=0</code>

<code>    </code><code>while</code> <code>[ $i -le 100 ] ; </code><code>do</code>

<code>            </code><code>let</code> <code>i++           </code><code>//前面不能用let $i++</code>

<code>            </code><code>if</code>  <code>[  $[$i%2] -eq 0 ] ;then  </code><code>//此处只能使用[ ] 进行引用</code>

<code>                    </code><code>let</code> <code>evensum+=$i</code>

<code>            </code><code>else</code>

<code>                    </code><code>continue</code>

<code>            </code><code>fi</code>

<code>    </code><code>done</code>

<code>    </code><code>echo </code><code>"Even sum is $evensum"</code>

    //求所有奇数之和2500    

<code>    </code><code>declare -i evensum=0</code>

<code>    </code> 

<code>    </code><code>while</code> <code>[ $i -lt 100 ] ; </code><code>do</code>    <code>//必须是小于100,否则会出错</code>

<code>        </code><code>let</code> <code>i++</code>

<code>        </code><code>if</code>  <code>[  $[$i%2] -eq 1 ] ;then</code>

<code>            </code><code>let</code> <code>evensum+=$i</code>

<code>        </code><code>else</code> 

<code>            </code><code>continue</code> 

<code>        </code><code>fi</code>

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

<code>    </code><code>#!/bin/bashk</code>

<code>    </code><code>declare -i oddsum=0</code>

<code>    </code><code>declare -i i=1</code>

<code>    </code><code>while</code> <code>true</code><code>; </code><code>do</code>

<code>        </code><code>let</code> <code>oddsum+=$i</code>

<code>        </code><code>let</code> <code>i+=2</code>

<code>        </code><code>if</code> <code>[ $i -gt 100 ];then</code>

<code>            </code><code>echo $oddsum</code>

<code>            </code><code>break</code>

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

<code>        </code><code>if</code> <code>who |grep wolf &amp;&gt; /dev/</code><code>null</code> <code>; then</code>

<code>            </code><code>sleep 3</code>

<code>    </code><code>echo </code><code>"$(date +%F-%H-%M) wolf loggin..."</code> <code>&gt;&gt; /tmp/userlog.log</code>

脚本4:util实现脚本3

<code>    </code><code>until who | grep </code><code>"wolf"</code> <code>&amp;&gt; /dev/</code><code>null</code> <code>; </code><code>do</code>

<code>        </code><code>sleep 3</code>

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

<code>    </code><code>declare -i userid</code>

<code>    </code><code>while</code> <code>read i ;</code><code>do</code>

<code>            </code><code>userid=`echo $i | cut -d: -f3`</code>

<code>                </code><code>//注:同上userid=$(echo $i | cut -d: -f3)</code>

<code>            </code><code>if</code> <code>[ $[$userid%2] -eq 0 ] ;then</code>

<code>                    </code><code>echo $i | cut -d: -f1,7</code>

<code>    </code><code>done &lt; /etc/passwd</code>

<code>    </code><code>//另一种实现方式,while循环                      </code>

<code>        </code><code>userid=$(echo $i | cut -d: -f3)</code>

<code>        </code><code>username=$(echo $i | cut -d: -f1)</code>

<code>        </code><code>usershell=$(echo $i | cut -d: -f7)</code>

<code>        </code><code>if</code> <code>[ $[$userid%2] -eq 0 ] ;then</code>

<code>            </code><code>echo </code><code>"$username $userid $usershell"</code>

<code>     </code><code>done &lt; /etc/passwd</code>

脚本6:for的特殊用法

<code>    </code><code>declare -i sum=0</code>

<code>    </code><code>for</code> <code>((i=1;i&lt;=100;i++));</code><code>do</code>

<code>            </code><code>let</code> <code>sum+=$i</code>

<code>    </code><code>echo </code><code>"Sum: is .$sum"</code>

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

<code>    </code><code>#</code>

<code>    </code><code>for</code> <code>((i=1;i&lt;=9;i++));</code><code>do</code>

<code>        </code><code>for</code> <code>((j=1;j&lt;=i;j++));</code><code>do</code>

<code>            </code><code>echo -e -n </code><code>"${i}*${j}=$[$i*$j]\t"</code>

<code>        </code><code>done</code>

<code>        </code><code>echo  </code><code>//这个echo用于换行,因为前面不换行了</code>

三、多分支if

多分支if

    if condation1;then

        ..

    elif

        ...

    else

    fi

    单分支if

示例1:显示一个菜单给用户

    要求:

        1.提示用户给出自己的选择

        2.正确的选择,则给出相应的信息,否则提示,用户重新选择

<code>    </code><code>cat &lt;&lt; EOF</code>

<code>    </code><code>cpu) display cpu information</code>

<code>    </code><code>mem) display memory information</code>

<code>    </code><code>disk) display disks information</code>

<code>    </code><code>quit) quit</code>

<code>    </code><code>===============================</code>

<code>    </code><code>EOF</code>

<code>    </code><code>read -p </code><code>"Enter your choice: "</code> <code>opt</code>

<code>    </code><code>while</code> <code>[ </code><code>"$opt"</code> <code>!= </code><code>"cpu"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"mem"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"disk"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"disk"</code> <code>-a "$</code>

<code>    </code><code>opt</code><code>" != "</code><code>quit</code><code>" ] ;do    read -p "</code><code>Enter your choice: " opt</code>

<code>    </code><code>if</code> <code>[ </code><code>"$opt"</code> <code>== </code><code>"cpu"</code> <code>] ;then</code>

<code>        </code><code>lscpu</code>

<code>    </code><code>elif [ </code><code>"$opt"</code> <code>== </code><code>"mem"</code> <code>] ;then</code>

<code>        </code><code>free -m</code>

<code>    </code><code>elif [ </code><code>"$opt"</code> <code>== </code><code>"disk"</code> <code>] ;then</code>

<code>        </code><code>fdisk -l /dev/sd[a-z]     </code>

<code>    </code><code>else</code>

<code>        </code><code>echo </code><code>"quit"</code>

<code>        </code><code>exit 0</code>

<code>    </code><code>fi</code>

四、case语句的语法格式

    case $VAR in  //仅仅支持glob风格的通配符

    PAT1)

        ;; //双分号结尾

    PAT2)

        ;; //

    ...

    *)

        ;;

    esac

    注意:    

        case支持glob风格的通配符

            *:任意长度的任意字符

            ?:任意单个字符

            []:范围内的

            a|b :a或者b

case实现示例

<code>    </code><code>case</code> <code>$opt </code><code>in</code> 

<code>    </code><code>cpu)        </code><code>//不用加“ ”</code>

<code>        </code><code>;;        </code><code>//最后要加 ;;</code>

<code>    </code><code>disk)</code>

<code>        </code><code>fdisk -l /dev/sd[a-z]</code>

<code>        </code><code>;;</code>

<code>    </code><code>mem)</code>

<code>    </code><code>*)</code>

<code>        </code><code>exit 0     ;;</code>

<code>    </code><code>esac</code>

五、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 //

    全局变量:

    环境变量:

    全局变量和局部变量对比:

<code>        </code><code>#!/bin/bash</code>

<code>        </code><code>name=tom</code>

<code>        </code><code>setname() {</code>

<code>            </code><code>local name=jerry</code>

<code>            </code><code>echo </code><code>"Function name:$name"</code>

<code>        </code><code>}</code>

<code>        </code><code>setname</code>

<code>        </code><code>echo </code><code>"Shell: $name"</code>

<code>    </code><code>[root@localhost ~]# bash 2.sh</code>

<code>    </code><code>Function name:jerry</code>

<code>    </code><code>Shell: tom</code>

七、函数递归 //自己调用自己

    函数间接或者直接就调用自身

    10!=10*9!=10*9*8!=...

<code>#!/bin/bash</code>

<code>fact() {</code>

<code>    </code><code>if</code> <code>[ $1 -eq 0 -o $1 -eq 1 ] ;then </code><code>//[ $1 -eq 0 ] || [ $1 -eq 1 ] 这样也可以</code>

<code>        </code><code>echo $1</code>

<code>        </code><code>echo $[$1*$(fact $[$1-1])]</code>

<code>}</code>

<code>fact $1</code>

<code>fab() {</code>

<code>    </code><code>if</code> <code>[ $1 -eq 1 ] ;then</code>

<code>        </code><code>echo -n </code><code>"1 "</code>

<code>    </code><code>elif [ $1 -eq 2 ] ;then</code>

<code>        </code><code>echo -n  </code><code>"1 "</code>

<code>        </code><code>echo -n </code><code>"$[$(fab $[$1-1]+$(fab $[$1-2])]"</code>

<code>}        </code>

<code>for</code> <code>i </code><code>in</code> <code>$(seq 1 $1) ;</code><code>do</code>

<code>    </code><code>fab $i</code>

<code>done</code>

<code>echo</code>

服务启动服务框架

    $lockfile,值/var/lock/subsys/SCRIPT_NAME

    1.可以接受的参数start,stop,restart,status四个参数

    2.如果参数非此四个,则显示帮助后退出

    3.start,创建lockfile,并显示启动:stop,则创建lockfile,并显示停止;restart,则先删除此文件,再创建此文件,而后显示重启完成,;

        statue根据lockfile是否存在,显示running/stopped

    注:务必使用case语句

<code>#</code>

<code># chkconfig: - 50 50</code>

<code># description test_service_script</code>

<code>prog=$(basename $0)</code>

<code>lockfile=/</code><code>var</code><code>/</code><code>lock</code><code>/subsys/$prog</code>

<code>case</code> <code>$1 </code><code>in</code>

<code>start)</code>

<code>    </code><code>if</code> <code>[ -f $lockfile ] ;then</code>

<code>        </code><code>echo </code><code>"$prog is running yet."</code>

<code>        </code><code>touch $lockfile </code>

<code>        </code><code>[ $? -eq 0 ] &amp;&amp; echo </code><code>"Start $prog finished.."</code>

<code>    </code><code>;;</code>

<code>stop)</code>

<code>        </code><code>rm -f $lockfile</code>

<code>        </code><code>[ $? -eq 0 ] &amp;&amp; echo </code><code>"$prog stopped.."</code>

<code>        </code><code>echo </code><code>"$prog is not running.."</code>

<code>restart)</code>

<code>    </code><code>if</code> <code>[ -f $lockfile ] ; then    </code>

<code>        </code><code>touch $lockfile</code>

<code>        </code><code>echo </code><code>"$prog restart finished.."</code>

<code>        </code><code>echo </code><code>"$prog start finished.."</code>

<code>status)</code>

<code>        </code><code>echo </code><code>"$prog is running.."</code>

<code>        </code><code>echo </code><code>"$prog is stopped.."</code>    

<code>*)</code>

<code>    </code><code>echo </code><code>"Usage: $prog {start|stop|resatrt|status}"</code>

<code>esac                    </code>

<code>    </code><code>cp service /etc/init.d/service</code>

<code>    </code><code>chmod +w /etc/init.d/service</code>

<code>    </code><code>chkconfig --add service</code>

<code>    </code><code>service service start</code>

八、function脚本

1.给定一个用户名,获取其id和shell

<code>    </code><code>userinfo() {</code>

<code>        </code><code>if</code> <code>id </code><code>"$username"</code> <code>&amp;&gt; /dev/</code><code>null</code> <code>;then    </code>

<code>            </code><code>grep </code><code>"$username"</code> <code>/etc/passwd | cut -d: -f3,7</code>

<code>        </code><code>else</code>

<code>            </code><code>echo </code><code>"No $username such user.."</code>

<code>    </code><code>}</code>

<code>    </code><code>username=$1</code>

<code>    </code><code>userinfo         </code><code>//调用该函数,可以调用多次</code>

<code>    </code><code>username=$2</code>

<code>    </code><code>userinfo</code>

2.升级版    

<code>    </code><code># chkconfig: - 50 50</code>

<code>    </code><code># description test_service_script</code>

<code>    </code><code>prog=$(basename $0)</code>

<code>    </code><code>lockfile=/</code><code>var</code><code>/</code><code>lock</code><code>/subsys/$prog</code>

<code>    </code><code>start() {</code>

<code>        </code><code>if</code> <code>[ -f $lockfile ] ;then</code>

<code>            </code><code>echo </code><code>"$prog is running yet."</code>

<code>            </code><code>touch $lockfile </code>

<code>            </code><code>[ $? -eq 0 ] &amp;&amp; echo </code><code>"Start $prog finished.."</code>

<code>    </code><code>stop() {</code>

<code>            </code><code>rm -f $lockfile</code>

<code>            </code><code>[ $? -eq 0 ] &amp;&amp; echo </code><code>"$prog stopped.."</code>

<code>            </code><code>echo </code><code>"$prog is not running.."</code>

<code>    </code><code>restart() {</code>

<code>        </code><code>if</code> <code>[ -f $lockfile ] ; then    </code>

<code>            </code><code>touch $lockfile</code>

<code>            </code><code>echo </code><code>"$prog restart finished.."</code>

<code>            </code><code>echo </code><code>"$prog start finished.."</code>

<code>    </code><code>status() {</code>

<code>            </code><code>echo </code><code>"$prog is running.."</code>

<code>            </code><code>echo </code><code>"$prog is stopped.."</code>    

<code>    </code><code>usage() {</code>

<code>        </code><code>echo </code><code>"Usage: $prog {start|stop|resatrt|status}"</code>

<code>    </code><code>case</code> <code>$1 </code><code>in</code> 

<code>    </code><code>start)</code>

<code>        </code><code>start ;;</code>

<code>    </code><code>stop)</code>

<code>        </code><code>stop ;;</code>

<code>    </code><code>restart)</code>

<code>        </code><code>restart;;</code>

<code>    </code><code>status)</code>

<code>        </code><code>status;;</code>

<code>        </code><code>usage;;</code>

3.添加10个用户

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

<code># 5: user is exists</code>

<code>adduser() {</code>

<code>    </code><code>if</code> <code>id $1 &amp;&gt; /dev/</code><code>null</code><code>; then</code>

<code>        </code><code>return</code> <code>5</code>

<code>        </code><code>useradd $1</code>

<code>        </code><code>retval=$?</code>

<code>        </code><code>return</code> <code>$retval  </code>

<code>for</code> <code>i </code><code>in</code> <code>{1..10} ;</code><code>do</code>

<code>        </code><code>adduser ${1}$i </code>

<code>        </code><code>a=$?  </code><code>//$?不要直接引用,如果需要多次引用的话,进行赋值变量</code>

<code>    </code><code>if</code> <code>[ $a -eq 0 ] ;then</code>

<code>         </code><code>echo </code><code>"useradd succeed..."</code>

<code>    </code><code>elif [ $a -eq 5 ] ;then</code>

<code>         </code><code>echo </code><code>"user ${1}$i is exists ,useradd failure."</code>

<code>         </code><code>echo </code><code>"Unknown errors.."</code> 

<code></code>

本文转自MT_IT51CTO博客,原文链接:http://blog.51cto.com/hmtk520/1979188,如需转载请自行联系原作者