shell循環:for、while、until——詳解

循環執行 :將某代碼段重複運行屢次; 重複運行多少次: 循環次數事先已知 ;循環次數事先未知 ;有進入條件和退出條件。html

三種循環體:for、while、until。git

再循環前前介紹步進,在循環中常常用到步進。web

步進centos

顯示1-10bash

[root@centos6mini app]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@centos6mini app]# echo $(seq 1 10)
1 2 3 4 5 6 7 8 9 10

1-10 遞加網絡

[root@centos6mini app]# echo {1..10..2}
1 3 5 7 9
[root@centos6mini app]# echo $(seq 1 2 10)
1 3 5 7 9

1-10 遞減併發

[root@centos6mini app]# echo {10..1..2}
10 8 6 4 2
[root@centos6mini app]# echo $(seq 10 -2 1)
10 8 6 4 2

1-100間的奇數和偶數app

[root@centos6mini app]# echo {1..100..2}
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
[root@centos6mini app]# echo {2..100..2}
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
[root@centos6mini app]# echo {100..1..2}
100 98 96 94 92 90 88 86 84 82 80 78 76 74 72 70 68 66 64 62 60 58 56 54 52 50 48 46 44 42 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2
[root@centos6mini app]# echo {99..1..2}
99 97 95 93 91 89 87 85 83 81 79 77 75 73 71 69 67 65 63 61 59 57 55 53 51 49 47 45 43 41 39 37 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1

隨機生成16位包含數字、大小寫字母、符號的密碼
dom

cat /dev/urandom |tr -dc '0-9a-zA-Z!@_#?.,' |head -c 16

tr -d 和 tr -dc 的用法ide

[root@centos6mini app]# echo 12324345 |tr -d 2 #不要數字2
134345
[root@centos6mini app]# echo 12324345 |tr -dc 2 #支取數字2
22

for循環

        for 變量名 in 列表;do 
                循環體 
        done

執行機制:

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

for循環的列表生成方式:

            (1) 直接給出列表

            (2) 整數列表:

                      (a) {start..end}

                    (b) $(seq [start [step]] end)

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

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

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

批量建立user1至user10,要求設置隨機16位密碼,包含數字、大小寫字母、符號。並要求用戶使用密碼首次登陸後,強制設置新密碼。

#!/bin/bash
> /root/user.log
for i in {1..10};do
#建立十個用戶
        useradd user$i && echo user$i is created
#隨機生成密碼
        password=$(cat /dev/urandom |tr -dc '0-9a-zA-Z!@_#?.,' |head -c 16)
#將用戶和密碼導出
        echo user$i:$password >> /root/user.log
#設置密碼
        echo $password |passwd --stdin user$i &> /dev/null
#強制下次登陸修改密碼
        passwd -e user$i &> /dev/null
done

使用♥,利用for,顯示出一個等腰三角形。

方法一:

for ((i=1;i<10;i++))
do
        for ((j=1;j<=i;j++))
do
                echo -n "♥"
        done
        echo
done
for ((i=1;i<9;i++))
do
        for ((j=9;j>i;j--))
do
                echo -n "♥"
        done
        echo
done

♥
♥♥
♥♥♥
♥♥♥♥
♥♥♥♥♥
♥♥♥♥♥♥
♥♥♥♥♥♥♥
♥♥♥♥♥♥♥♥
♥♥♥♥♥♥♥♥♥
♥♥♥♥♥♥♥♥
♥♥♥♥♥♥♥
♥♥♥♥♥♥
♥♥♥♥♥
♥♥♥♥
♥♥♥
♥♥
♥

方法二:

#!/bin/bash2
read -p "請輸入三角形的高度: " num
for i in  `seq $num`;do
        for x in `seq 1 $[$num-$i]`;do
                echo -e " \c"
        done
        for n in `seq 1 $[2*$i-1]`;do
                #yanse=`tr -dc '1-6' < /dev/urandom  | head -c 1`
                #echo -e "\e[3"$yanse"m♥\e[0m\c"
                echo -e "\e[34m♥\e[0m\c"
        done
        echo 
done
   ♥        
  ♥♥♥
 ♥♥♥♥♥
♥♥♥♥♥♥♥

方法三

#!/bin/bash
for ((i = 1; i < 10; i++))
do
   for ((j = 10; j > i; j--))
   do  
      echo -n " ";
   done
   for ((m = 1; m <= i; m++))
   do  
       echo -n "$i "
   done
   echo ""
done
[root@centos7 ~]# ./sjx 
         1 
        2 2 
       3 3 3 
      4 4 4 4 
     5 5 5 5 5 
    6 6 6 6 6 6 
   7 7 7 7 7 7 7 
  8 8 8 8 8 8 8 8 
 9 9 9 9 9 9 9 9 9


方法四

#!/bin/bash
#彩色閃爍山角形
read -p "請輸入三角形邊長: " w
for (( i=1;i<=$w;i++ )); do
        for(( j=$w;j>$i;j--  ));do
                echo -n " "
        done
        for (( m=1;m<=i;m++   ));do
                we=`cat /dev/urandom |tr -dc '1-6' |head -c 1 `
                echo -e  "\033[3"$we";5m♥\033[0m\c"   #紅色加閃爍
                done
        echo

done

添加10個用戶user1-user10,密碼爲8位隨機字符、

#!/bin/bash
> /root/user.log
for i in {1..10};do    
    useradd user$i && echo user$i is created
    pass=$(cat /dev/urandom |tr -dc '0-9a-zA-Z!@_#?.,' |head -c 16)   #生成隨機數
    echo user$i:---pass:$pass >> /root/user.log
    echo $pass |password --stdin user$i &> /dev/null
done
/etc/rc.d/rc3.d目錄下分別有多個以K開頭和以S開頭的文件;分別讀取每一個文件,以K開頭的輸出爲文件加stop,以S開頭的輸出爲文件名加start,如K34filename stop  S66filename start
#!/bin/bash
for i in $(ls /etc/rc.d/rc3.d/);do   #查看文件內容肯定循環次數
        if [[ $i =~ ^K.* ]];then
                echo "$i stop"
        elif [[ $i =~ ^S.* ]];then
                echo "$i start"
        fi
done
[root@centos6mini app]# ./linshi 
K05wdaemon stop
K10saslauthd stop
K15htcacheclean stop
K15httpd stop
K30spice-vdagentd stop
K50dnsmasq stop
K50kdump stop
K73winbind stop
K74ntpd stop
...省略...

編寫腳本,提示輸入正整數n的值,計算1+2+…+n的總和

#!/bin/bash
read -p "請輸入一個正整數" s
w=0
if [[ "$s" =~ ^[0-9]+$ ]] ;then
    for i in  $(seq 1 $s) ;do
    w=$[$w+$i]                      
    
    done
    echo "整數1到$s的和爲$w"
else echo "請輸入正整數"
fi

計算100之內全部能被3整除的整數之和

方法一:

[root@centos6mini app]# echo {3..100..3} |tr " " "+"|bc    #進行步進,替換相加
1683

方法二:

#!/bin/bash
for i in {3..100..3};do    #步進,相加
 n=$[$n+$i]  &> /devnull
 done
echo $n
方法三:
#!/bin/bash
sum=0
for n in $(seq 1 100);do
        i=$[$n/3]    #進行相除
        y=$[3*$i]    #進行相乘 、運算成功則成立
        if [ $y -eq $n ];then
                sum=$[$n+$sum]
        fi
done  
        echo $sum

方法四:

sum=0
for i in {1..100};do
    if [ $[$i%3] -eq 0 ];then  #相除取餘進行斷定
    let sum+=$i   #進行加法運算
    fi  
done
echo $sum

打印九九乘法表

for (( i=1 ;i<=9;i++ ));do
        for ((n=1;n<=9;n++)) ;do
                w=0
                w=$[$n*$i]
        if [ $n -le $i   ];then
        echo -n  " $i*$n=$w "
        fi
        done
echo
done

在/testdir目錄下建立10個html文件,文件名格式爲數字N(從1到10)加隨機8個字母,如:1AbCdeFgH.html

方法一:

#!/bin/bash
cd /testdir &> /dev/null
if [ ! $(echo $?) -eq 0 ] ;then   #判斷文件是否存在
    mkdir /testdir &> /dev/null
fi

for i in $(seq 1 10 );do
    w=$(cat /dev/urandom |tr -dc '0-9a-zA-Z!@_#?.,' |head -c 8)
    touch $i$w.html
done

方法二:

if ! [ -d /testdir ];then   #判斷文件是否存在
  mkdir /testdir &> /dev/null   #若是沒有建立文件
fi
for i in {1..10};do  
  touch /testdir/$i`cat /dev/urandom |tr -dc [:alpha:] |head -c 8`.html    #建立文件
done

探測局域網內的主機

    172.18.250-254.X

    能ping通顯示並保存至/root/ip.log

    要求並行探測提升效率。

   
[root@centos6mini zuoye]# cat 11.sh 
 #!/bin/bash
> /root/ip.log
for i in {250..255};do
    for n in {1..255};do
    {
    ping -c1 -w1 172.18."$i"."$n" &> /dev/null
    if [ $? -eq  0  ] ;then
    echo "ping 172.18."$i"."$n"  is up"  #>> /root/ip.log
    fi
    }&
    done
done

[root@centos6mini zuoye]# ./11.sh 
ping 172.18.250.14  is up
ping 172.18.250.26  is up
ping 172.18.250.71  is up
ping 172.18.250.81  is up
ping 172.18.250.112  is up
ping 172.18.250.154  is up
ping 172.18.250.164  is up
ping 172.18.250.166  is up
ping 172.18.250.183  is up
ping 172.18.250.195  is up
ping 172.18.250.212  is up
ping 172.18.250.216  is up
ping 172.18.250.224  is up
ping 172.18.250.249  is up
ping 172.18.250.250  is up
ping 172.18.251.18  is up

打印國際象棋棋盤


方法一:

[root@centos6mini zuoye]# cat qipan.sh 
#!/bin/bash
for n in {1..8};do
    for i in {1..8} ;do
        if [ $[$n%2]  -eq 0   ];then
            if [ $[$i%2]  -eq 0   ];then
                 echo -e "\033[41m  \033[0m\c"
            fi
            if [ $[$i%2] -ne 0   ] ;then
                  echo -e "\033[47m  \033[0m\c"
                
            fi
        else
             if [ $[$i%2]  -eq 0   ];then
                                  echo -e "\033[47m  \033[0m\c"
                        fi
                        if [ $[$i%2] -ne 0   ] ;then
                                 echo -e "\033[41m  \033[0m\c"
                        
                        fi

        fi
    done
    echo 
done

方法二:

#!/bin/bash
for xline in $(seq 1 8);do   #橫向
  for yline in $(seq 1 8);do   #縱向
        if  [ $[$[$xline+$yline]%2] -eq 0 ];then   #判斷;橫向與縱向相加,最後相除是否等於0
          echo -e "\033[47m  \033[0m\c"
        else
          echo -e "\033[41m  \033[0m\c"
        fi
  done
  echo 
done

方法三:(放大版)

#!/bin/bash
for i in {1..8};do
        for x in {1..4};do  #控制單行大小。對已有輸出進行放大
                for n in {1..8};do
                        a=`echo $[$[$i+$n]%2]`
                        if [ $a -eq 0 ];then
                                echo -e "\e[43m" "" "" "" "" "" "" "" "\e[0m\c"
                        else
                                echo -e "\e[42m" "" "" "" "" "" "" "" "\e[0m\c"
                        fi
                done
                echo
        done
done








while循環

            while CONDITION; do 
                    循環體
             done

CONDITION:循環控制條件;進入循環以前,先作一次判 斷;每一次循環以後會再次作判斷;條件爲「true」,則執行 一次循環;直到條件測試狀態爲「false」終止循環

所以:CONDTION通常應該有循環控制變量;而此變量的值 會在循環體不斷地被修正

    進入條件:CONDITION爲true

    退出條件:CONDITION爲false


「:」 和true的返回值都爲真

[root@centos6mini zuoye]# true
[root@centos6mini zuoye]# echo $?
0
[root@centos6mini zuoye]# :
[root@centos6mini zuoye]# echo $?
0

判斷/var/目錄下全部文件的類型

[root@centos6mini app]# cat  linshi 
#!/bin/bash
dc=0
lc=0
cc=0
bc=0
oc=0
zc=0

ls -l /var |grep -v total >/tmp/var_ftype.txt
while read lines
do
   ftype=`echo $lines |awk '{print $1}' |cut -c 1`
   case $ftype in
        d) dname=`echo $lines |awk '{print $9}'`; echo "$dname is a Directory" ; let dc+=1;;
        l) lname=`echo $lines |awk '{print $9}'`; echo "$lname is a Links of Soft " ;let lc+=1 ;;
        c) cname=`echo $lines |awk '{print $9}'`; echo "$cname is a Character of file" ;let cc+=1;;
        b) bname=`echo $lines |awk '{print $9}'`; echo "$bname is a Block file" ; let bc+=1;;
        -) zname=`echo $lines |awk '{print $9}'`; echo "$zname is a common file" ; let zc+=1;;
        *) echo "Others files"; let oc+=1

   esac

done </tmp/var_ftype.txt
echo '-----------------------------' 
echo -e "var目錄下普通文件數量: $zc\nvar目錄下子目錄數量:$dc\nvar目錄下連接文件數量:$lc\nvar目錄下字符類型文件數量: $cc\nvar
目錄下塊設備文件數量:$bc\n其餘類型文件數量:$oc"
rm -f /tmp/var_ftype.txt


[root@centos6mini app]# ./linshi 
cache is a Directory
crash is a Directory
cvs is a Directory
db is a Directory
empty is a Directory
games is a Directory
gdm is a Directory
lib is a Directory
local is a Directory
lock is a Directory
log is a Directory
mail is a Links of Soft 
nis is a Directory
opt is a Directory
preserve is a Directory
run is a Directory
spool is a Directory
tmp is a Directory
www is a Directory
yp is a Directory
-----------------------------
var目錄下普通文件數量: 0
var目錄下子目錄數量:19
var目錄下連接文件數量:1
var目錄下字符類型文件數量: 0
var
目錄下塊設備文件數量:0
其餘類型文件數量:0

編寫腳本,求100之內全部正奇數之和

方法一:

[root@centos6mini zuoye]# echo {1..100..2}
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
[root@centos6mini zuoye]# echo {1..100..2}|tr " " + |bc
2500

方法二:

[root@centos6mini 3.19]# ./1
2500
[root@centos6mini 3.19]# cat 1
#!/bin/bash
u=0 
for i in  {1..100..2}; do
    let u+=i
done
echo $u


方法三

[root@centos6mini 3.19]# ./1
2500
[root@centos6mini 3.19]# cat 1 
#!/bin/bash
u=0 
i=1
while [ $i -le 100 ] ;do

    let u+=i
    let i+=2
done
echo $u

編寫腳本,提示請輸入網絡地址,如192.168.0.0,判斷輸入的網段中主機在線狀態,並統計在線和離線主機各多少

方式一:

#!/bin/bash
w=0
a=0
y=0
for (( d=0;d<256;d++ ));do
    for (( f=1;f<255;f++  ));do
        {
        ping -c1 -w1 172.18."$d"."$f" &> /dev/null
        a=`echo $?`

        if [ $a -eq 0 ] ; then 
            echo "172.18."$d"."$f"  up" >> /app/e.txt
            echo "172.18."$d"."$f"  up "    
        fi
        if [ $a -ne 0 ] ; then 
                        echo "172.18."$d"."$f"  down " >> /app/r.txt
            echo "172.18."$d"."$f"  down "                  
        fi
    }&
    done
done 
w=`cat /app/e.txt |wc -l`
echo "通的 :  $w"
y=`cat /app/r.txt |wc -l`
echo "不通的 :  $y"
rm -rf /app/e.txt
rm -rf /app/w.txt

方式二:

#!/bin/bash
i=1
q=1
w=0
a=0
y=0
while [ $i -lt  255  ];do
    while [ $q  -lt  255 ];do
        {
        ping -c1 -w1 172.18."$i"."$q" &> /dev/null
        a=`echo $?`
        if [ $a -eq 0 ] ; then 
            echo "172.18."$i"."$q"   up" >> /app/e.txt
            echo "172.18."$i"."$q"   :up"
        fi
        if [ $a -ne 0 ] ; then 
                       echo "172.18."$i"."$q"  down "   >> /app/w.txt
                
               echo "172.18."$i"."$q"  down "

        fi
        }&
        let q=q+1

        
    done
    
    let   i=i+1
    q=1      ####將q的變量值重新賦值爲1
done 
w=`cat /app/e.txt |wc -l`
echo "通的主機數爲 :  $w"
y=`cat /app/w.txt |wc -l`
echo "不通的主機數爲 :  $y"
rm -rf /app/w.txt /app/e.txt

圖片.png


編寫腳本,打印九九乘法表


[root@centos6mini 3.19]# cat 99 
#!/bin/bash
q=1
w=1
while [ $q -le 9 ];do
    while [ $w -le 9 ];do
        e=0
        let e=q*w   
        if [ $w -le $q ];then
        echo  -n "  $w*$q=$e  "
        fi

    let w+=1
    done
    let q+=1
    w=1
    echo
done
[root@centos6mini 3.19]# ./99
  1*1=1  
  1*2=2    2*2=4  
  1*3=3    2*3=6    3*3=9  
  1*4=4    2*4=8    3*4=12    4*4=16  
  1*5=5    2*5=10    3*5=15    4*5=20    5*5=25  
  1*6=6    2*6=12    3*6=18    4*6=24    5*6=30    6*6=36  
  1*7=7    2*7=14    3*7=21    4*7=28    5*7=35    6*7=42    7*7=49  
  1*8=8    2*8=16    3*8=24    4*8=32    5*8=40    6*8=48    7*8=56    8*8=64  
  1*9=9    2*9=18    3*9=27    4*9=36    5*9=45    6*9=54    7*9=63    8*9=72    9*9=81

四、編寫腳本,利用變量RANDOM生成10個隨機數字,輸出這個10數字,並顯示其中的最大值和最小值

[root@centos6mini 3.19]# ./4
25955
25748
16113
19729
8944
19049
16202
20067
30609
4309
最大值: 30609
最小值: 4309
[root@centos6mini 3.19]# cat 4 
#!/bin/bash
q=1
while [ $q -le 10 ] ;do
     echo $[RANDOM] &>> /app/o.txt
     #echo $[RAND0M] #每次隨機都是新的值
    let q+=1    
done
cat /app/o.txt
w=`cat  /app/o.txt |sort -rn |tail -n1`
e=`cat /app/o.txt |sort -rn | head  -n 1`
echo "最大值: $e"
echo "最小值: $w"
rm -rf /app/o.txt


五、編寫腳本,實現打印國際象棋棋盤[

[root@centos6mini 3.19]# cat 5,sh
#!/bin/bash
q=1
w=1
while [ $q -le 8 ]  ;do
    while [ $w -le 8 ] ;do
        if [ $[$[$q+$w]%2] -eq 0 ] ;then   ##判斷句中的計算須要$[]括起來:
            echo -e "\033[47m  \033[0m\c"
        else
            echo -e "\033[41m  \033[0m\c"
        fi
    
    let w+=1
    done
    let q+=1
    w=1
    echo
done

後續六個字符串:efbaf275cd、4be9c40b8b、44b2395c4六、f8c8873ce0、b902c16c8b、ad865d2f63是經過對隨機數變量RANDOM隨機執行命令:

   echo $RANDOM|md5sum|cut –c1-10

   後的結果,請破解這些字符串對應的RANDOM值


方法一:

#!/bin/bash
>6
while true ;do
        while true ;do
                w=`echo $RANDOM `  #定義變量--隨機數隨時在變化,給他賦值一個變量,後邊取值就不在變化了
                q=`echo $w|md5sum|cut -c1-10`
                if [ $q == efbaf275cd  ] ;then
                        echo "efbaf275cd=$w" #>>6
                elif [ $q == 4be9c40b8b  ] ;then
                        echo "4be9c40b8b=$w" #>>6
                elif [ $q  == 44b2395c46  ] ;then
                        echo "44b2395c46=$w" #>>6
                elif [ $q == f8c8873ce0  ] ;then
                        echo "f8c8873ce0=$w" #>>6
                elif [ $q == b902c16c8b  ] ;then
                         echo "b902c16c8b=$w" #>>6
                elif [ $q == ad865d2f63 ] ;then
                         echo "ad865d2f63=$w" #>>6
                fi

        done
done
[root@centos6mini ~]# cat 6 |sort|uniq
44b2395c46=9000
4be9c40b8b=12000
ad865d2f63=1000
b902c16c8b=3000
efbaf275cd=15000
f8c8873ce0=6000

方法二:

#!/bin/bash
sum=0
for i in {1..32767};do
        num=`echo $i |md5sum | cut -c1-10`
        case $num in
                efbaf275cd|4be9c40b8b|44b2395c46|f8c8873ce0|b902c16c8b|ad865d2f63)
                        echo $i
                        let sum++
                ;;
        esac
        if [ $sum -lt 6 ];then
                continue
        else
                break
        fi
done

$#和$*差異

[root@centos6mini 3.19]# ./linshi  1 2 2 3 4
1 2 2 3 4
2 2 3 4
2 3 4
3 4
4
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
while [ $# -gt 0 ];do    
    echo $*
    shift
done

[root@centos6mini 3.19]# ./linshi  1 2 2 3 4
5
4
3
2
1
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
while [ $# -gt 0 ];do    
    echo $#
    shift
done

使用一條命令,依次建立指定的用戶。如執行createuser.sh tom bob alice harry

方法1:

[root@centos6mini 3.19]# ./linshi createuser.sh tom bob alice harry 
createuser.sh 用戶建立成功
tom 用戶建立成功
bob 用戶建立成功
alice 用戶建立成功
harry 用戶建立成功
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
#!/bin/bash
while [ $# -gt 0 ]
do 
        

        id $1 &>/dev/null
        if [ $? -eq 0 ];then
                echo $1 is already exsit.
                shift
                continue
        fi
        useradd $1
        echo "$1 用戶建立成功"
        shift

done

刪除用戶
[root@centos6mini 3.19]# ./linshi createuser.sh tom bob alice harry 
createuser.sh 用戶刪除成功
tom 用戶刪除成功
bob 用戶刪除成功
alice 用戶刪除成功
harry 用戶刪除成功
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
while [ $# -gt 0 ];do 
           userdel -r  $1
           echo "$1 用戶刪除成功"
           shift
done

方法2:

#!/bin/bash
while [ $# -gt 0 ];do
        id $1 &> /dev/null && { echo $1 is alread exist && shift && continue; }
        useradd $1 && echo  $1 is created
        shift
done

每隔3秒鐘到系統上獲取已經登陸的用戶的信息;若是發現用戶hacker登陸,則將登陸時間和主機記錄於日誌/var/log/login.log中,並退出腳本

#!/bin/bash
while true;do
if $(ps -au |grep "^hacker.*" &> /dev/null);then   #監測前臺終端上有沒有用戶登錄信息
        echo $(ps -au |grep "^hacker.*" |tr -s " " |cut -d" " -f1,7,9) >> /var/log/login.log
            #將用戶登錄信息保存到日誌文件中/var/log/login.log
        break   #推出監測
else
        sleep 3s   #三秒已監測,防止程序太多佔用cpu
fi
done

隨機生成10之內的數字,實現猜字遊戲,提示比較大或小,相等則退出

[root@centos6mini 3.19]# ./linshi 
請輸入數值 :  1
錯了 ,小了
請輸入數值 :  9
錯誤,大了
請輸入數值 :  5
猜對了
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
qe=$( echo $[$RANDOM%10] )  
while true ;do
read -p "請輸入數值 :  " qw
        if  [ $qw -gt $qe   ] ;then
                echo "錯誤,大了"

        elif [ $qw -lt $qe   ] ;then
                echo "錯了 ,小了"
        elif [ $qe -eq $qw  ];then
                echo "猜對了"
                break
        fi

done

用文件名作爲參數,統計全部參數文件的總行數

[root@centos6mini 3.19]# ./linshi /etc/passwd /etc/sysconfig/network-scripts/ifcfg-eth1 /etc/passwd
89
[root@centos6mini 3.19]# cat linshi 
#!/bin/bash
sumhang=0
while [ $# -gt 0  ];do
        hang=$( cat $1 | wc -l  )
        let sumhang+=hang
        shift
done
echo $sumhang

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

方法一:

#!/bin/bash
min=$1  #最小值等於第一個數值
max=$1  #最大數等於第一個數值

while [ $# -gt 0 ];do    #進行數值數量進行判斷,作循環
        value=$1     #定義變量
        if [ $value  -gt $max ];then   #當第二個數大於第一個數時
                max=$value  #最大值等於後一個數值,對max重新賦與新的值
        elif [ $value -lt $min ];then    #當第二個數大於第一個數時
                min=$value   #最小值等於後一個數值 對min重新賦與新的值
        fi
        shift #無論前面判斷是否成立,都進行數列左移,
done
echo "min $min"
echo "max $max"

方法二:

#!/bin/bash
if [ $# -lt 2 ];then  #對輸入數字數量進行檢測
        echo "type more than two numbers"
        exit 1
fi

small=$(echo $* |xargs -n1 |sort -n |head -n 1)   #進行數值排序
big=$(echo $* |xargs -n1 |sort -n |tail -n 1)
echo "Maximum number is $big"
echo "Minimum number is $small"

[root@localhost ~]# echo 1 -3 -99 46 7  32 43 2133 312 |xargs -n1  #以一數列進行顯示
1
-3
-99
46
7
32
43
2133
312

read 示例:

[root@centos6mini 3.19]# while read -p "type your name: " name ;do  echo your is $n$name; done
type your name: zhangsan
your is zhangsan
type your name: lisi
your is lisi
type your name: wangwu
your is wangwu
type your name: ^C

[root@centos6mini 3.19]# read bing < test。txt
[root@centos6mini 3.19]# echo $bing   
hello

^C
[root@centos6mini 3.19]# while read name ; do echo $name ;done  # 沒有指定輸入
123     #輸入
123     #輸出
qwe       #輸入
qwe     #輸出
asd     #輸入
asd     #輸出
zxc     #輸入
zxc     #輸出
^C^[[A^C
[root@centos6mini 3.19]# while read name ; do echo $name ;done <6   #name爲變量,輸入來自文件文件內容讀取完了,循環中止
hello
qweqew
12341234
asdas
ads
sda
sad
asd
as
asd
as
read 示例:

顯示UID小於1000的爲sys user,大於等於1000的爲comm user。

[root@centos6mini 3.19]# cat linshi       
#!/bin/bash
while read usline ;do  #經過read ,定義變量值usline
        usuid=$(  echo $usline |cut -d: -f3 ) ,#引用變量usline ,並定義變量usuid
        usname=$( echo $usline |cut -d: -f1 )  #引用變量usline ,並定義變量usname
        #if [ $usuid -lt 1000 ];then   #進行判斷
        if (( $usuid < 1000 )) ;then   #進行判斷(兩種方式都可以)
                echo "$usname is a sys user"
        else 
                echo "$usname is a comm user"
        fi

done < /etc/passwd  #每次循環引用文件內容一行,進行操做,引用完了,循環中止。
[root@centos6mini 3.19]# ./linshi   
root is a sys user
bin is a sys user
daemon is a sys user
adm is a sys user
lp is a sys user
sync is a sys user
shutdown is a sys user
halt is a sys user
mail is a sys user
uucp is a sys user
operator is a sys user
games is a sys user
gopher is a sys user
ftp is a sys user
nobody is a sys user
vcsa is a sys user
saslauth is a sys user

找出分區利用率大於10%的分區,併發出警告/dev/sdaX will be full: 15%要求使用while read來實現


答案1:

#!/bin/bash
df |grep /dev/sd > /app/fenqu
while read line;do
        used=$(echo $line |tr -s " " % |cut -d% -f5)
        name=$(echo $line |cut -d" " -f1)
        if (( $used > 10 ));then
                echo "$name will be full:$used%"
        fi
done < /app/fenqu


[root@centos6mini 3.19]# df |grep /dev/sd >/app/zuoye/3.19/6
[root@centos6mini 3.19]# cat /app/zuoye/3.19/6
/dev/sda5      28564480 1872060  25234756  7% /
/dev/sda2      20511356  70276  19392504  1% /app
/dev/sda1        194241  31785    152216  18% /boot
[root@centos6mini 3.19]# while read line ;do
> used=$(echo $line |tr -s " " % |cut -d% -f5)
>  name=$(echo $line |cut -d" " -f1)
> if (( $used > 10 ));then
>  echo "$name will be full:$used%"
> fi
> done </app/zuoye/3.19/6
/dev/sda1 will be full:18%
答案2:
#!/bin/bash
> df_h
df -h | grep ^/dev/[sh]d* >> df_h
while read disk;do
    a=`echo $disk |grep -o "\<[0-9]\{0,3\}%" | cut -d% -f1`
    b=`echo $disk |grep -o "^[^[:space:]]\+\>"`
    if [ $a -gt 10 ];then
        echo "$b will be full: $a%"
    fi  
done < df_h
答案3:sed實現  
#!/bin/bash
df |grep /dev/sd |while read disk;do
        diskused=$(echo $disk |sed -r 's/.* ([0-9]+)%.*/\1/')
        diskname=$(echo $disk |sed -r 's@(/dev/sd[[:lower:]][[:digit:]]).*@\1@')
        if (( $diskused > 10 ));then
                echo "$diskname will be full:$diskused%"
        fi
done

until循環

            until CONDITION; do 
                        循環體 
            done

    
    進入條件: CONDITION 爲false

    退出條件: CONDITION 爲true


循環控制語句continue
用於循環體中

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

while CONDTIITON1; do 
      CMD1
       ... 
       if CONDITION2; then 
        continue 
         fi 
       CMDn

循環控制語句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

特殊用法

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

while read line; do 
        循環體
done < /PATH/FROM/SOMEFILE

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

二、雙小括號方法,即((…))格式,也能夠用於算術運算

雙小括號方法也可使bash Shell實現C語言風格的變量操做

        I=10

        ((I++))

for循環的特殊格式: for ((控制變量初始化;條件判斷表達式;控制變量的修正表達 式)) 
do 
        循環體
done

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

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


select循環與菜單

select variable in list
    do 
        循環體命令 
    done

select 循環主要用於建立菜單,按數字順序排列的 菜單項將顯示在標準錯誤上,並顯示 PS3 提示符, 等待用戶輸入

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

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


select與case

select 是個無限循環,所以要記住用 break 命令退 出循環,或用 exit 命令終止腳本。也能夠按 ctrl+c 退出循環

select 常常和 case 聯合使用

與 for 循環相似,能夠省略 in list,此時使用位置 參量


信號捕捉trap

trap '觸發指令' 信號

            自定義進程收到系統發出的指定信號後,將執行觸發指令 ,而不會執行原操做

trap '' 信號

            忽略信號的操做

trap '-' 信號

            恢復原信號的操做

trap -p

            列出自定義信號操做


文件測試

    -z string 測試指定字符是否爲空,空着真,非空爲假
    -n string 測試指定字符串是否爲不空,空爲假 非空爲真    -e FILE 測試文件是否存在    -f file 測試文件是否爲普通文件    -d file 測試指定路徑是否爲目錄
    -r file 測試文件對當前用戶是否可讀
    -w file 測試文件對當前用戶是否可寫
    -x file 測試文件對當前用戶是均可執行
    -z  是否爲空  爲空則爲真    -a  是否不空
    -u  file :是否存在且擁有suid權限 
    -g  file :是否存在且擁有sgid權限 
    -k  file :是否存在且擁有sticky權限
[root@centos6mini 3.19]# [ -n ""  ]&& echo true   #空爲假
[root@centos6mini 3.19]# [ -n "1"  ]&& echo true   #非空爲真
true
[root@centos6mini 3.19]# [ -n "  "  ]&& echo true   #非空爲真
true
[root@centos6mini 3.19]# [ -n   ]&& echo true    #非空爲真
true
[root@centos6mini 3.19]# [ -z   ]&& echo true   #空爲真
true
[root@centos6mini 3.19]# [ -z "" ]&&echo true  #空爲真
true
[root@centos6mini 3.19]# [ -z "1" ] && echo true      "#非空爲假
[root@centos6mini 3.19]# [ -z "  " ] && echo true      #非空爲假

掃描/etc/passwd文件每一行,如發現GECOS字段爲空,則填充用戶名和單位電話爲62985600,並提示該用戶的GECOS信息修改爲功。 

#!/bin/bash
cat /etc/passwd |while read userline;do  #用管道實現給循環while賦值
        if [ -n "$(echo $userline |cut -d: -f5)" ];then    #-n "1" 非空爲真
                continue     #爲真時啥都不作
        else
                username=$(echo $userline|cut -d: -f1)
                usermod -c $username-62985600 $username
                echo $username\'s gecos already changed!
        fi
done

特殊用法

雙小括號方法,即((…))格式,也能夠用於算術運算 

雙小括號方法也可使bash Shell實現C語言風格的變量操做 

I=10 

((I++)) 

for循環的特殊格式: 

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

do 

    循環體

done

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

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

16077c1b-7b7a-489a-abc8-1ef4989b0797.jpg



練習:計算從1加到100的和。

#!/bin/bash
sum=0
for ((i=1;i<=100;i++));do
        let sum+=i
done
echo sum=$sum
unset sum i
  
sum=0
i=1
while [ $i -le 100 ];do
        let sum+=i
        let i++
done
echo sum=$sum
select循環與菜單

select variable in list 

do 

        循環體命令 

done 

select 循環主要用於建立菜單,按數字順序排列的 菜單項將顯示在標準錯誤上,並顯示 PS3 提示符, 等待用戶輸入

 

 PS3="Please choose your menu: "

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

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

[root@centos6mini 3.19]# ./linshi     
1) huangmenji
2) huimian
3) hulatang
4) roujiamo
Please choose your menu: 1
The price is $15
Please choose your menu: 2
The price is $10
Please choose your menu: 3
The price is $8
Please choose your menu: 4
The price is $6
Please choose your menu: 5
get out

[root@centos6mini 3.19]# cat ./linshi   
#!/bin/bash

select menu in huangmenji huimian hulatang roujiamo;do 
        case $REPLY in
                1) echo "The price is \$15";;
                2) echo "The price is \$10";;
                3) echo "The price is \$8";;
                4) echo "The price is \$6";;
                *) echo "get out";break;;
        esac
done

信號捕捉trap 

trap '觸發指令' 信號

        自定義進程收到系統發出的指定信號後,將執行觸發指令 ,而不會執行原操做 

trap '' 信號 忽略信號的操做 

rap '-' 信號 恢復原信號的操做 

trap -p 列出自定義信號操做

trap 全部可選項

[root@centos6mini 3.19]# trap -l 
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

#!/bin/bash 
trap 'echo 「signal:SIGINT"'  int     # int 至關與Ctrl+c
trap -p 
for((i=0;i<=10;i++)) 
do 
sleep 1
echo $i 
done
trap ''  int #trap '' 信號 忽略信號的操做 
trap -p 
for((i=11;i<=20;i++)
do 
sleep 1
echo $i 
done 
trap '-'  int   #rap '-' 信號 恢復原信號的操做 
trap -p 
for((i=21;i<=30;i++)
do 
sleep 1 
echo $i
done




忽略kill -15 ,操做能夠成功

ef1b777a-c538-4e83-b89a-26de8eb6ebe7.jpg


忽略kill -9操做 ,不成功,沒法忽略kill -9


85693952-6647-4f49-8659-47a8baaa03c1.jpg

trap -l,把全部信號打印出來



查看kill -9 和kill -15 對應的信號選項 

afc41590-b38e-4936-bc13-7160ac361cfa.png

select與case 

select 是個無限循環,所以要記住用 break 命令退 出循環,或用 exit 命令終止腳本。也能夠按 ctrl+c 退出循環

select 常常和 case 聯合使用 

與 for 循環相似,能夠省略 in list,此時使用位置

相關文章
相關標籤/搜索