Linux學習之路-Linux-循環 for、while【10】---20171223

循環

循環執行
>將某代碼段重複運行多次
>重複運行多少次
>>循環次數事先已知
>>循環次數事先未知

>有進入條件和退出條件

for, while, until

for循環

  • 用法:

    for NAME [in WORDANDS; S ...]; do COMMdone

    for 變量名 in 列表;do 
    循環體
    done
  • 執行機制:

    依次將列表中的元素賦值給“變量名”; 每次賦值後即執 行一次循環體; 直到列表中的元素耗盡,循環結束

  • 列表生成方式:

    直接給出列表
    整數列表:
    > {start..end}
    >$(seq [start [step]] end)

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

    使用glob,如:.sh
    變量引用; $@, $

  • 練習
1、判斷/var/目錄下所有文件的類型  --->在做一次
#!/bin/bash
for i in /var/* ;do
if [ -b $i ];then
        echo "$i是塊設備"
elif [ -c $i ] ;then
        echo "$i是字符設備"
elif [ -f $i ];then
        echo "$i是普通文件"
elif [ -h $i ];then
        echo "$i是符號鏈接文件"
elif [ -p $i ];then
        echo "$i是管道文件"
elif [ -S $i ];then
        echo "$i是套接字文件"
elif [ -d $i ];then
        echo "$i是目錄文件"
else
         echo "文件或目錄不存在"
fi
done

2、添加10個用戶user1-user10,密碼爲8位隨機字符,並且把生成的用戶名及密碼保存到/app/newuser.txt文件中
#!/bin/bash
for i in `seq 1 5` ; do
        username=user$i
        useradd $username
        password=`openssl rand -base64 10 | head -c 8`
        echo $password | passwd --stdin $username &> /dev/null
        echo $username $password >> /app/password.txt
done
echo "ok"

3、/etc/rc.d/rc3.d目錄下分別有多個以K開頭和以S開頭的文件 ;分別讀取每個文件,以K開頭的輸出爲文件加stop,以S開頭的輸 出爲文件名加start,如K34filename stop S66filename start   --->在做一次
#!/bin/bash
for i in /etc/rc.d/rc3.d/[SK]* ;do
if [ $(basename $i | cut -c1) == "K" ] ;then
    echo "`basename $i` stop"
else
    echo "`basename $i` start"
fi
done

4、編寫腳本,提示輸入正整數n的值,計算1+2+...+n的總和
#!/bin/bash
read -p "Please input a positive integer: " num
for i in `seq 1 $num` ; do
        let sum+=$i
done
echo $sum

5、計算100以內所有能被3整除的整數之和
#!/bin/bash
for i in `seq 0 3 100` ; do
        let sum+=$i
done
echo $sum      ------>1683

6、計算100以內所有不能被3整除的整數之和
for i in `seq 1 100` ; do
        if [ "$[i%3]" -ne 0 ] ; then
                let sum+=$i
        fi
done
echo $sum        ------>3376

7、編寫腳本,提示請輸入網絡地址,如192.168.0.0,判斷輸入的網段中主機在線狀態
#!/bin/bash
> /app/ip.log
read -p "Please input the network(eg:172.18.1.0): " network
[[ "$network" =~ ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] || { echo "Please input a legal IP " ; exit 250; }    ----->**一定要注意250後的分號,機器容易忽略的位置**
net=`echo $network | cut -d. -f 1-3`
for i in {1..254} ; do
        {
        if ping -c 1 -w 1 $net.$i &> /dev/null ; then
                echo $net.$i is up | tee -a /app/ip.log
        else
                echo $net.$i is down
        fi
        }&
done
wait

8、打印九九乘法表
#!/bin/bash
for i in `seq 1 9` ; do
        for j in `seq $i` ; do
                echo -e "${j}x${i}=$[i*j]\t\c"
        done
        echo
done

9、在/testdir目錄下創建10個html文件,文件名格式爲數字N(從1到10)加隨機8個字母,如:1AbCdeFgH.html
#!/bin/bash
for i in {1..10} ; do
        touch /testdir/"$i"`openssl rand -base64 100 | tr -dc '[:alpha:]' | head -c 8`.html
done

10、打印等腰三角形
#!/bin/bash
read -p "Please enter a number: " x
for i in `seq $x` ; do
        let space=$x-$i
        let xing=2*$i-1
        for j in `seq $space` ; do
                echo -e " \c"
        done
        for k in `seq $xing` ; do
                echo -e "*\c"
        done
        echo
done

until循環

  • 用法
    until CONDITION; do 
       循環體
    done
    進入條件: CONDITION 爲false 
    退出條件: CONDITION 爲true

循環控制語句continue

  • continue用於循環體中
  • continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;最內層爲第1層
  • 用法:
    while CONDTIITON1; do
      CMD1
      ...
      if CONDITION2; then
            continue 
            fi
     CMDn
     ... 
    done

循環控制語句break

  • break用於循環體中
  • break [N]:提前結束第N層循環,最內層爲第1層
  • 用法:
    while CONDTIITON1; do 
        CMD1
        ...
        if CONDITION2; then
                 break 
       fi
       CMDn
       ... 
    done

循環控制shift命令

  • shift [n]
  • 用於將參量列表 list 左移指定次數,缺省爲左移一次。
  • 參量列表 list 一旦被移動,最左端的那個參數就從列表中刪 除。while 循環遍歷位置參量列表時,常用到 shift
  • ./doit.sh a b c d e f g h
  • ./shfit.sh a b c d e f g h
示例:doit.sh
#!/bin/bash
# Name: doit.sh
# Purpose: shift through command line arguments # Usage: doit.sh [args]
while [ $# -gt 0 ] # or (( $# > 0 )) ; do
       echo $*
       shift 
done

示例:shift.sh
#!/bin/bash
#step through all the positional parameters 
until [ -z "$1" ] ; do
       echo "$1"
       shift 
done
echo

for 特殊用法

  • 雙小括號方法,即((...))格式,也可以用於算術運算
  • 雙小括號方法也可以使bash Shell實現C語言風格的變量操作

    I=10
    ((I++))

  • 控制變量初始化:僅在運行到循環代碼段時執行一次
  • 控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而後再做條件判斷
  • 用法

    for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))
    do
         循環體
    done
    for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
        Arithmetic for loop.
    
       Equivalent to
                    (( EXP1 ))
                    while (( EXP2 )); do
                                COMMANDS
                                (( EXP3 ))
         done

    Linux學習之路-Linux-循環 for、while【10】---20171223

示例:
1、求1-100的和
寫法1
#!/bin/bash
sum=o
for ((i=1;i<=100;i++)) ; do
        let sum+=i
done
echo sum=$sum

寫法2
for ((sum=0,i=1;i<=100;i++)) ; do
        let sum+=i
done
echo sum=$sum

2、求1-100中 3 的整數倍的和
用for寫法
for ((sum=0,i=0;i<=100;i+=3)) ; do
        let sum+=i
done
echo sum=$sum
用while寫法
sum=0
i=0
while [ "$i" -le 100] ; do
        let sum+=i
        let i+=3
done
echo sum=$sum

3、打印9x9表
for ((i=1;i<=9;i++)) ; do
        for ((j=1;j<=i;j++)) ; do
                echo -ne "${j}x${i}=$[$i*$j]\t" ;
        done
        echo
done
  • 練習
1、每隔3秒鐘到系統上獲取已經登錄的用戶的信息;如果發 現用戶hacker登錄,則將登錄時間和主機記錄於日誌 /var/log/login.log中,並退出腳本 --->在做一次
#!/bin/bash
username=cent
{
while true ;do
    if who | egrep "^\b$username\b" &> /dev/null ;then
        who | egrep "^\b$username\b" >> /var/log/login.log
        echo "$username 已登錄"
        echo "fuck ,go out my system" | write $username
    else
        echo "$username 已下線"
    fi
    sleep 3
done
}

2、隨機生成10以內的數字,實現猜字遊戲,提示比較大或小 ,相等則退出
suiji=`echo $[$RANDOM%10+1]`
read -p "Please input a number in 1-10: " num
until [[ "$num" -eq "$suiji" ]] ; do
        if [[ "$num" -lt "$suiji" ]] ; then
                read -p "less than random: " num
        else
                read -p "much than random: " num
        fi
done
echo -e "\e[32mCongratulations! The random is $suiji!\e[37m"

3、用文件名做爲參數,統計所有參數文件的總行數

4、用二個以上的數字爲參數,顯示其中的最大值和最小值

while 循環

  • 用法

    while CONDITION; do 
         循環體
    done

    CONDITION:循環控制條件;進入循環之前,先做一次判 斷;每一次循環之後會再次做判斷;條件爲“true”,則執行 一次循環;直到條件測試狀態爲“false”終止循環
    因此:CONDTION一般應該有循環控制變量;而此變量的值 會在循環體不斷地被修正
    進入條件:CONDITION爲true
    退出條件:CONDITION爲false

  • 創建無線循環
    while true; do 
         循環體
    done
  • while循環的特殊用法

    遍歷文件的每一行

    while read line; do
    循環體
    done &lt; /PATH/FROM/SOMEFILE
    依次讀取/PATH/FROM/SOMEFILE文件中的每一行,
    且將行賦值給變量line
    示例:
    掃描/etc/passwd文件每一行,如發現GECOS字段爲空,則填 充用戶名和單位電話爲62985600,並提示該用戶的GECOS信 息修改成功。
  • 練習
1、編寫腳本,求100以內所有正奇數之和
#!/bin/bash
i=1
while [ "$i" -le 100 ] ; do
        if [ $[$i%2] -ne 0 ] ; then
                let sum+=$i
        fi
        let i++
done
echo $sum

2、編寫腳本,提示請輸入網絡地址,如192.168.0.0,判斷輸入的網段中主機在線狀態,並統計在線和離線主機各多少
#!/bin/bash
read -p "Please input the network(eg:172.18.0.1): " network
[[ "$network" =~ ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-9])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-9])$ ]] || { echo "Please input a legal IP " ; exit 250 ; }
net=`echo $network | cut -d. -f 1-3`
i=1
up=0
down=0
while [ "$i" -le 254 ] ; do
        ping -c 1 -w 1 $net.$i &> /dev/null && { echo $net.$i is up ; let ++up ; } || { echo $net.$i is down ; let down++ ; }
        let i++
done
wait
echo i=$i
echo up host is $up
echo down host is $down

3、編寫腳本,打印九九乘法表
#!/bin/bash
i=1
j=1
while [ $i -le 9 ] ;do
    while [ $j -le $i  ] ;do
        echo -ne "${j}x${i}=$[i*j]\t"
        let j+=1
    done
    let i+=1
    j=1
    echo
done

4、編寫腳本,利用變量RANDOM生成10個隨機數字,輸出 這個10數字,並顯示其中的最大值和最小值
#!/bin/bash
let i=0,min=max=$RANDOM
echo "$min "
while [ $i -lt 9  ];do
    ran=$RANDOM
    echo "$ran "
    if [ $ran -ge $max ];then 
        let max=ran
    fi
    if [ $ran -le $min ];then
        let min=ran
    fi
    let i+=1
done
echo "最大值是 $max ,最小值是 $min"

5、編寫腳本,實現打印國際象棋棋盤
#!/bin/bash
let x=y=1
h=8
while [ $x -le $h ];do
    while [ $y -le $h ];do
        if [ $[(x+y)%2] -eq 0 ]  ;then
            echo -en "\033[47m  \033[0m"
        else
            echo -en "\033[40m  \033[0m"
        fi
    let y+=1
    done
    echo
let x+=1,y=1
done

6、後續六個字符串:efbaf275cd、4be9c40b8b、 44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63 是通過對隨機數變量RANDOM隨機執行命令:echo $RANDOM|md5sum|cut –c1-10 後的結果,請破解這些字符串對應的RANDOM值
 #!/bin/bash
 key_num_array=(efbaf275cd 4be9c40b8b 44b2395c46 f8c8873ce0 b902c16c8b ad865d2f63)
 for true_num in `seq 0 65535`;do
      key_num=`echo $true_num | md5sum | cut -c 1-10`
      for num in  ${key_num_array[*]}; do
             if [ "$key_num" == "$num" ];then
                   echo "$num --> $true_num" 
            fi                                                                       
     done
done

7 、檢測httpd服務是否處於開啓狀態,如果處於關閉狀態,即刻開啓服務
#!/bin/bash
sleeptime=30
while true ; do
        if killall -0 httpd &> /dev/null ; then
                true
        else
                service httpd restart
                time=`date +"%F %T"`
                echo "At $time httpd is restart" >> /app/httpd.log
        fi
        sleep $sleeptime
done

8、檢測磁盤利用率,如果大於80,就發出警報,每5分鐘檢測一次
第一種方法:
while true ; do
        df -h | grep "/dev/sd" | while read disk ; do
                per=`echo $disk | sed -r 's/.* (.*)%.*/\1/'`
                part=`echo $disk | cut -d" " -f1`
                [ "$per" -gt 80 ] && echo "$part will be full,over 80%"
        done
        sleep 300
done
第二種方法-做成計劃任務調用腳本,腳本內容如下
used=10
df -h | grep "/dev/sd" | while read disk ; do
        per=`echo $disk | sed -r 's/.* (.*)%.*/\1/'`
        part=`echo $disk | cut -d" " -f1`
        [ "$per" -gt "$used" ] && echo "$part will be full,over ${used}%"
done

select循環與菜單

  • select 循環主要用於創建菜單,按數字順序排列的 菜單項將顯示在標準錯誤上,並顯示 PS3 提示符,等待用戶輸入
  • 用戶輸入菜單列表中的某個數字,執行相應的命令
  • 用戶輸入被保存在內置變量 REPLY
  • 用法
    select variable in list 
    do
           循環體命令
    done
  • select 是個無限循環,因此要記住用 break 命令退 出循環,或用 exit 命令終止腳本。也可以按 ctrl+c 退出循環
  • select 經常和 case 聯合使用
  • 與 for 循環類似,可以省略 in list,此時使用位置 參量
示例:
1、用while完成的菜單
#!/bin/bash
cat <<EOF
1 yxrs
2 gbjd
3 lzjd
4 lamian
5 huimian
6 yangroutang
7 quit
EOF
while read -p "Please choose the menu number: " menu ; do
        case $menu in
        1|2)
                echo The price is 20
                ;;
        3|6)
                echo The price is 25
                ;;
        4|5)
                echo The price is 15
                ;;
        7)
                break
                ;;
        *)
                echo "Please choose again"
                ;;
        esac
done

2、用select 完成
PS3="Please choose the menu number: "
select menu in gbjd yxrs lamian huimian baoyu quit ; do
        case $menu in
        gbjd|yxrs)
                echo The price is 25
                ;;
        lamian|huimian)
                echo The price is 15
                ;;
        baoyu)
                echo The price is 100
                ;;
        quit)
                break
                ;;
        *)
                echo "Try choose again"
                ;;
        esac
done

3、select 與 $REPLY 配合
PS3="Please choose the menu number: "
select menu in gbjd yxrs lamian huimian baoyu quit ; do
        case $REPLY in
        1|2)
                echo The price is 25
                ;;
        3|4)
                echo The price is 15
                ;;
        5)
                echo The price is 100
                ;;
        6)   
                break
                ;;
        *)
                echo "Try choose again"
                ;;
        esac
done

trap 信號捕捉

  • trap '觸發指令' 信號 自定義進程收到系統發出的指定信號後,將執行觸發指令,而不會執行原操作
  • 用法

    trap '' 信號
    >忽略信號的操作

    trap '-' 信號
    >恢復原信號的操作

    trap -p
    >列出自定義信號操作

  • trap示例
#!/bin/bash
trap 'echo “signal:SIGINT"' int 
trap -p
for((i=0;i<=10;i++))
do
       sleep 1
       echo $i 
done
trap '' int
trap -p 
for((i=11;i<=20;i++)) 
do
      sleep 1
      echo $i 
done
trap '-' int
trap -p 
for((i=21;i<=30;i++)) 
do
     sleep 1
     echo $i 
done

#!/bin/bash
trap `echo Do not break` INT
fo i in {1..10} ; do
      echo $i
            sleep 0.5
done
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章