shell編程之循環及函數

for 循環

for 變量名 in 列表;do

   循環體

done  

執行機制: 依次將列表中的元素賦值給“變量名”; 每次賦值后即執行一次循環體; 直到列表中

的元素耗盡,循環結束

 

列表生成方式:

(1)直接給出列表

(2)整數列表:

(a) {start..end}

(b) $(seq [start [step]] end)  : `seq 1 2 100`

(3)返回列表的命令 $(COMMAND)

(4)使用glob,如:*.sh

(5)變量引用;$@, $*

 

while 循環

while CONDITION;do

循環體

  done

   CONDITION :循環控制條件;進入循環之前,先做一次判斷;每一次循環之后會再次做判  斷;條件為“true”則執行一次循環;直到條件測試狀態為“false”終止循環

 因此:CONDTION 一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正

 進入條件:CONDITION true 退出條件:CONDITION false

 

until 循環

until CONDITION;do

循環體

   done

 進入條件:CONDITION true; 退出條件:CONDITION false

 

循環控制語句continue

用于循環體中

continue [N] :提前結束第N 層的本輪循環,而直接進入下一輪判斷;最內層為第1

while CONDTIITON1; do

CMD1

if CONDITION2; then

continue

fi

CMDn

done

 

循環控制語句break

用于循環體中

break [N] :提前結束第N 層循環,最內層為第1

while CONDTIITON1; do

CMD1

if CONDITION2; then

break

fi

CMDn

done

 

創建無線循環

while true;do

   循環體

done

until falsedo

    循環體

done

 

while 循環的特殊用法(遍歷文件的每一行)

while read line; do

循環體

done < /PATH/FROM/SOMEFILE

依次讀取/PATH/FROM/SOMEFILE 文件中的每一行,且將行賦值給變量line

 

for 循環的特殊格式:

for (( 控制變量初始化; 條件判斷表達式; 控制變量的修正表達式))

do

循環體

done

控制變量初始化:僅在運行到循環代碼段時執行一次

控制變量的修正表達式: 每輪循環結束會先進行控制變量修正運算,而后再做條件判斷

雙小括號方法,即(()) 格式,如((i=1,i++,i<=10))

 

例:

 blob.png

打印310~20(排除15

continue改為continue 2 break  跳出里面的for循環,則打印310~14

若改為break 2,則跳出整個循環,只打印10~14

 

select循環與菜單

select variable in list

do

循環體命令

done

select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示PS3提示

示符,等待用戶輸入

用戶輸入菜單列表中的某個數字,執行相應的命令

用戶輸入被保存在內置變量 REPLY

select是個無限循環,因此要記住用break命令退出循環,或用 exit命令終止腳本,

也可以按 ctrl+c退出循環。select 經常和case聯合使用

1: select cmd in ls pwd  hostname exit;do $cmd;done

blob.png

注意:輸入4,執行exit就登出shell 

2

blob.png

blob.png

 

 

函數

function f_name {

    函數體

}

f_name() {

    函數體

}

函數的定義和使用:

    可在交互式環境下定義函數

    可將函數放在腳本文件中作為它的一部分

    可放在只包含函數的單獨文件中

調用:函數只有被調用才會執行;

    調用:給定函數名

    函數名出現的地方,會被自動替換為函數代碼

函數的生命周期:被調用時創建,返回時終止

 

函數的執行結果返回值:

    (1) 使用echo printf 命令進行輸出

    (2) 函數體中調用命令的輸出結果

函數的退出狀態碼:

    (1) 默認取決于函數中執行的最后一條命令的退出狀態碼

    (2) 自定義退出狀態碼,其格式為:

    return 從函數中返回,用最后狀態命令決定返回值

return 0 無錯誤返回

return 1-255 有錯誤返回

 

使用函數文件

可以將經常使用的函數存入函數文件,然后將函數文件載入shell

一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂?/span>set命令查看所有定義的函數,其輸出列表包括已經載入shell 的所有函數;若要改動函數,首先用unset命令從shell中刪除函數,改動完畢后,再重新載入此文件

function fun1 (){ echo "this is a fun1";}

# fun1  輸出this is a fun1

set命令看到存在內存中的變量fun1

unset fun1 set查看就沒有這個變量了,# fun1 輸出command not found

 

function fun3 () { echo "this is a func3";return;echo "xxxx"; }

#fun3 只輸出this is a func3  return后面的不執行

echo $? 返回0

return后面自定義級別,如return 100

執行fun3 echo $? 返回100


載入函數

filename source filename


函數變量

變量作用域:

環境變量:當前shell和子shell有效

本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此本地變量的作用范圍是當前shell 腳本程序文件,包括腳本中的函數。

局部變量:函數的生命周期;函數結束時變量被自動銷毀

注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量

  在函數中定義局部變量的方法 local NAME=VALUE


1.判斷/var/ 目錄下所有文件的類型

 blob.png

  for i in /var/*;do echo $i|filetype.sh;done |sed -n '2~2p'    (用到函數調用)

2.添加10個用戶user1-user10,密碼同用戶名

 #!/bin/bash

for i in {1..10}

do

useradd user$i

echo "user$i"|passwd –stdin user$i

done

3./etc/rc.d/rc3.d 目錄下分別有多個以K開頭和以S開頭的文件;分別讀取每個文件,以K 開頭的文件輸出為文件加stop,以S開頭的文件輸出為文件名加start;

  “K34filename stop” “S66filename start”

  #!/bin/bash

cd /etc/rc.d/rc3.d

for i in /etc/rc.d/rc3.d/*;do

b=`basename /etc/rc.d/rc3.d/$i`

j=`echo $b|cut -c1`

     if [ $j == 'K' ];then

     cp $b "$b"_stop

     elif [ $j == 'S' ];then

     cp $b "$b"_start

     fi

done

blob.png

4.寫一個腳本,提示輸入正整數n 的值,計算1+2+3+…n的總和

  #!/bin/bash

read -p "Input a positive number: " n

if [ $[$n/1] -gt 0 ];then

    echo sum=`seq -s+ 1 $n|bc`

elif [ $[$n/1] -lt 0 ];then

    echo negative number is not allowed

elif [ $n == 0 ];then

    echo Zero!

else

    echo other input is illegal

fi

blob.png

5.寫一個腳本,提示請輸入網絡地址,如172.18.18.0 ,判斷輸入的網段中主機在線狀態

#!/bin/bash

    for ip in `seq 1 255`

    do

    {

    ping -c 1 172.18.18.$ip > /dev/null 2>&1

    if [ $? -eq 0 ]; then

    echo 172.18.18.$ip UP

    else

    echo 172.18.18.$ip DOWN

    fi

    }&

    done

6.打印乘法表(if / while

#!/bin/sh

  for i in {1..9};do

    for ((j=1;j<=9;j++));do

      echo -n "$j*$i=$(($j*$i)) "

      if [ $j -ge $i ];then

       echo

       break

      fi

    done

done

#!/bin/sh

i=1

j=1

while [ "$i" -ne 10 ];do

    while [ "$j" -le $i ];do

        echo -ne "$i*$j=$(($i*$i)) \t"

        let j++

    done

    j=1

    let i++

    echo

done

blob.png

7.100以內所有正整數之和(while)

#!/bin/bash

read -p "Input a positive number: " n

a=0

while [ $a -le $n ];do

sum=`seq -s+ 1 $a`

let a++

done

echo $sum|bc

blob.png

8.通過ping 命令探測192.168.1.1-254范圍內的所有主機的在線狀態,統計在線主機和離線主機各多少

#!/bin/bash

read -p "Input the ip: " ip

i=`echo $ip | cut -d. -f1-3`.

j=0

if echo $ip | egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$" ;then

  while [ $j -le 255 ] ;do

    ping -c1 -W1 $i$j &> /dev/null  && echo "$i$j is online" ||echo "$i$j is offline"

    let j++

  done

else

  echo "Illegal input"

fi

blob.png

9.利用變量RANDOM生成10個隨機數字,輸出這個10數字,并顯示其中的最大者和最小者(while)

#!/bin/bash

echo > rnu

frequency=1

while [ $frequency -le 10 ];do

    echo $[$RANDOM] >> rnu

let frequency++

done

ten_random=`cat rnu|sed -e 1d`

echo  "Ten random number are"

echo $ten_random

echo -e "\033[31mmax=`cat rnu|tr " " "\n"|sort -n|tail -1`\033[0m"

echo -e "\033[32mmin=`cat rnu|tr " " "\n"|sort -n|sed -n 2p`\033[0m"

blob.png

10.打印國際象棋棋盤

 #!/bin/bash

for i in {1..8}; do

     for ((j=1;j<=8;j++)); do

       if [ $[($i+$j)%2] -eq 0 ]; then

         echo -ne "\033[47m  \033[0m"

       else

         echo -ne "\033[40m  \033[0m"

       fi

     if [ $j -eq 8 ]; then

       echo -ne "\n"

     fi

     done

done

blob.png

11.每隔3秒鐘到系統上獲取已經登錄的用戶的信息;如果發現用戶hacker 登錄,則將登錄時   間和主機記錄于日志/var/log/login.log , 并提示該用戶退出系統

#!/bin/bash

until who |grep -q "^hacker\b" ;do

    sleep 3

done

who | grep "^hacker"|tr -s ' '|cut -d' ' -f3,5 >> /var/log/login.log

echo "you should logout system" | mail hacker

echo "reminded and login record in /var/log/login.log"

blob.png

12. 隨機生成10以內的數字,實現猜字游戲,提示比較大或小,相等則退出。

  #!/bin/bash

  read -p "Input a number: " m

  n=$[$RANDOM%10+1]

  until [[ $m -eq $n ]];do

    [ $m -lt $n ] && echo "It's small,guess bigger"

    [ $m -gt $n ] && echo "It's big,guess smaller"

    read -p "Input a number: " m

  done

  echo Right!

  blob.png 

13.打印松塔

 #!/bin/bash

 #i是當前行數,j是空格數量,h是星號數量

read -p "Please Enter a number:" Row

for ((i=1; i<=Row; i++))

do

        for ((j=$Row-$i; j>0; j–));

        do

              echo -n ' '

        done

        for ((h=1; h<=$((2*$i-1)); h++))

        do

              echo -ne '\033[32m*\033[0m'

        done

        echo

done

blob.png

14.until循環實現國際象棋棋盤

 #!/bin/bash

i=1

j=1

until [ $i -gt 8 ]

do

      until [ $j -gt 8 ]

      do

          if [ $[(($i+$j))%2] -eq 1 ];then

                echo -ne "\033[47m  \033[0m"

          else

                echo -ne "\033[40m  \033[0m"

          fi

       let j++

      done

      echo

let i++

j=1

done

 blob.png

15.編寫服務腳本/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

fstart () {

    if [ -e "$1"  ]; then

        echo "Already start"

    else

        touch $ff

        echo "Start Successfully!"

    fi

} 

fstop () {

    if [ -e "$1" ] ; then

        rm -f $1

        echo "Stop Successfully!"

    else

        echo "Already stop"

    fi

} 

frestart() {

    if [ -e "$1" ] ; then

        fstop &> /dev/null

        fstart &> /dev/null

        echo "Restart successful"

    else

        fstart &> /dev/null

        echo "start successful "

    fi

} 

fstatus () {

    if [ -e "$1" ] ;then

        echo "testsrv is runing…"

    else

        echo "testsrv is stopped…"

    fi

} 

select choice in start stop restart status quit

do

    ff=/var/lock/subsys/testsrv.sh

    case $choice in

    start)

        fstart $ff

        ;;

    stop)

        fstop $ff

        ;;

    restart)

        frestart $ff

        ;;

    status)

        fstatus $ff

        ;;

    quit)

        break

        ;;

    *)

        echo "error!"

        exit 2

    esac

done

 blob.png

16. 編寫腳本/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

copycmd(){

for eachline in `ldd $fullname | sed -r -n 's@.*> (/.*) \(.*$@\1@p'`

do

   local path=`dirname $eachline`

   mkdir -p /mnt/sysroot/$path &>/dev/null

   cp -p $eachline  /mnt/sysroot/$path &>/dev/null

done

}

while true

do

read -p "請輸入一個可執行的命令名稱 " cmds

which $cmds

if [ $? -eq 0 ]

then

   fullname=`\which $cmds`

   path=`dirname $fullname`

   mkdir -p /mnt/sysroot/$path &>/dev/null

   cp -p $fullname  /mnt/sysroot/$path &>/dev/null

   copycmd

elif [[ $cmds == "quit" ]]

then

   break

else

   echo "輸入的命令不對"

fi

done

blob.png

blob.png

17.寫一個函數實現數字的加減乘除運算,例如輸入1+2 ,將得出正確結果

 vim mathfun

#!/bin/bash

function multiplications () {

let multiplication=$1\*$2

echo "積為:$multiplication"

}

function divisions () {

let division=$1/$2

echo "商為:$division"

}

function pluss () {

let plus=$1+$2

echo "和為:$plus"

}

function subtractions {

let subtraction=$1-$2

echo "差為:$subtraction"

}

vim funset

#!/bin/bash

source mathfun

echo "1st arg is $1"

echo "2st arg is $2"

pluss $1 $2

divisions $1 $2

multiplications $1 $2

subtractions $1 $2

blob.png

18. 0,1,2,3,5,8,13,21,34…… ,斐波納契數列以如下被以遞歸的方法定義:

   F(0)=0 ,F(1)=1 ,F(0)=F(n-1)+F(n-2) n2

寫一個函數,求n階斐波那契數列

#!/bin/bash

rabbit() {

    if [ $1 -eq 0 ];then

        echo 0

    elif [ $1 -eq 1 ];then

        echo 1

    else

        echo "$[$(rabbit $[$1-1])+$(rabbit $[$1-2])]"

    fi

}

rabbit $1

blob.png

19.利用函數,實現N片盤的漢諾塔的移動步驟

#!/bin/bash

hannuo() {

    if [ $1 -eq 1 ];then

        echo "from $2 to $4"

    else

        hannuo `expr $1 – 1` $2 $4 $3

        echo "from $2 to $4"

        hannuo `expr $1 – 1` $3 $2 $4

    fi

}

read -p "Input the number: " n

hannuo $n 'A' 'B' 'C'

blob.png

20.掃描/etc/passwd 文件每一行,如發現GECOS 字段為空,則填充用戶名和單位電話為62985        6并提示該用戶的GECOS信息修改成功

#!/bin/bash

    while read line ; do

        var=`echo $line | cut -d ":" -f 5`

        user=`echo $line | cut -d ":" -f 1`

        [[ -z "${var}" ]] && chfn -f ${user} -p 629856 ${user};echo "${user}'s information

    change successful"

    done < /etc/passwd

 blob.png



原創文章,作者:victorycommander,如若轉載,請注明出處:http://www.www58058.com/39013

(0)
victorycommandervictorycommander
上一篇 2016-08-24
下一篇 2016-08-24

相關推薦

  • Net22-第一周作業-linux基礎知識

    1、描述計算機的組成及其功能。    計算機硬件由五大部件組成,分別是運算器、控制器、存儲器、輸入和輸出設備組成。 其中,運算器和控制器合稱為cpu,接受指令,加工數據。 存儲器又分為內存和外存(硬盤、U盤等等),這里指的是內存,給cpu提供數據和指令。 輸入設備對數據進行輸入,如鼠標,鍵盤等。 輸出設備對計算結果進行顯示或者打印等,如顯…

    Linux干貨 2016-08-22
  • 程序包管理:rpm、yum以及(make)源代碼編譯安裝

    程序包管理:rpm、yum以及(make)源代碼編譯安裝 在Linux上安裝程序一般都有三種方法:源代碼編譯安裝,rpm包安裝和rpm包的前端安裝yum, (rpm,和yum程序包管理器是針對CentOS6平臺的) 程序包管理方式都大同小異:  源代碼–>目標二進制格式(二進制程序、庫文件、配置文件、幫助文件)–&gt…

    Linux干貨 2017-01-10
  • vim的簡單應用

    vim的簡單應用         之前我們學習過Linux的思想,其中有一條就是一切皆文本,所以在這里大部分配置文件都是文本模式存在的,那么使用簡單的文字編輯器就可以修改配置了,之前我們學習過nano文本編輯器,但是Vim會比nano使用的更為方便,也更強大。 基本現在所有的Li…

    2017-06-17
  • 第6天預習xargs命令的用法

    Xargs用法詳解 1. 簡介   之所以能用到這個命令,關鍵是由于很多命令不支持|管道來傳遞參數,而日常工作中有有這個必要,所以就有了xargs命令,例如: find /sbin -perm +700 |ls -l     &n…

    Linux干貨 2016-08-05
  • Linux命令date命令詳解

    在linux環境中,熟練運用date命令來表示自己想要表示的時間,肯定可以給自己的工作帶來諸多方便,下面是詳細的使用說明和示例 在linux環境中,不管是編程還是其他維護,時間是必不可少的,也經常會用到時間的運算,熟練運用date命令來表示自己想要表示的時間,肯定可以給自己的工作帶來諸多方便。 1.命令格式:date[參數]… [+格式] 2.命…

    2017-07-18
  • 馬哥教育網絡班20期+第3周課程練習

    1、列出當前系統上所有已經登錄的用戶的用戶名,注意:同一個用戶登錄多次,則只顯示一次即可。    w | grep "^root\>" |sort -u   2、取出最后登錄到當前系統的用戶的相關信息。    who |   3、取出當前系統上被用戶當作…

    Linux干貨 2016-06-26
欧美性久久久久