天天看點

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,如需轉載請自行聯系原作者