Shell編程、part3

本節內容

1. shell流程控制
2. for語句
3. while語句
4. break和continue語句
5. case語句
6. shell編程高級實戰node

shell流程控制

流程控制是改變程序運行順序的指令。linux shell有一套本身的流程控制語句,其中包括條件語句(if),循環語句(for,while),選擇語句(case)。下面我將經過例子介紹下,各個語句使用方法linux

if語句

格式:
格式:if list; then list; [ elif list; then list; ] ... [ else list; ] finginx

1.1 單分支

-if 條件表達式; then
-命令
-fiweb

實例:正則表達式

#!/bin/bash
 N=10
 if [ $N -gt 5 ]; then
  echo yes
 fi

# bash test.sh
yes

1.2 雙分支

if 條件表達式; then
  命令
else
命令
fishell

實例1:編程

#!/bin/bash
N=10
if [ $N -lt 5 ]; then
  echo yes 
else 
       echo no
fi
# bash test.sh
no

實例2:判斷crond進程是否正在運行bash

-v: 表示取反
-c: 即count,取代一般的輸出,顯示行數服務器

#!/bin/bash
NAME=crond
NUM=$(ps aux | grep $NAME | grep -vc grep) 
if [ $NUM -eq 1 ]; then
  echo "$NAME running."
else 
       echo "$NAME is not running!" 
fi

實例3:檢查主機是否在線
-c:表示發送幾回包
-w:表示等待時間。當試圖檢測不可達主機時此選項頗有用。命令行

#!/bin/bash 
if ping -c 1 192.168.1.1 &>/dev/null; then 
      echo "OK."
else 
      echo "NO!" 
fi

if 語句能夠直接對命令狀態進行判斷,就省去了獲取$?這一步!

1.3 多分支

if 條件表達式; then
  命令
elif 條件表達式; then
  命令
else 命令
fi

當不肯定條件符合哪個時,就能夠把已知條件判斷寫出來,作相應的處理。
實例1:

$1:表示接受用戶輸入參數

#!/bin/bash
N=$1
if [ $N -eq 3 ]; then
  echo "eq 3" 
elif [ $N -eq 5 ]; then
  echo "eq 5" 
elif [ $N -eq 8 ]; then
  echo "eq 8"
else 
      echo "no" 
fi

若是第一個條件符合就再也不向下匹配。

shell編程之if語句實戰案例

需求:
1. 完成用戶輸入文件或者目錄的自動複製,並能夠實現用戶指定複製目標位置。
2. 用戶體驗佳。

#!/bin/bash
read -p "pls enter a file you want to copy:" file 
if [ -f $file -o -d $file ];then
        read -p "do you want to copy the $file?(y/n)" sure
     confirm=$(echo ${sure} | tr A-Z a-z) 
        if [ "$confirm" == "y" ];then
                read -p "where do you want to copy?" dire 
                if [ -d $dire ];then
                        cp -a $file $dire
                        echo "the $file copied to $dire"
                else 
                        echo "the $dire is not exists" exit 1 
                 fi
        elif [ "$confirm" == "n" ];then
                echo "bye"
        else 
                echo "pls input y or n" 
        fi 
 else echo "the $file is not exists" 
fi

練習題1:嘗試寫一個shell簡單的計算器,實現加減乘除。
請輸入一個數字: 7
請輸入運算符:+
請輸入第二個數字:7
7+7=14

練習題2:輸入一個用戶,用腳本判斷判斷該用戶是否存在。

for語句

格式:for name [ [ in [ word ... ] ] ; ] do list ; done

for 變量名 in 取值列表; do
命令
done
或者
for 變量名 in 取值列表
do
命令
done

實例1:

#!/bin/bash 
for i in {1..3}; do 
        echo $i
done

# bash test.sh 
1
2
3

實例2:計算100之內偶數和

#!/bin/bash
sum=0
for i in `seq 2 2 100` 
do 
              let sum+=$i 
done
echo "$sum"

例子3:建立100個用戶並設置6位隨機密碼
[root@ken ~]# cat test9.sh

#!/bin/bash
for i in `seq 10`
do
useradd user$i
pass=`echo $RANDOM | md5sum | cut -c 1-6`
echo 「$pass」 | passwd --stdin 「user$i」
echo -e 「帳戶:user$i\n密碼:$pass」>> /root/passwd
done

執行結果:
[root@ken ~]# cat passwd
帳戶:user1
密碼:69a70a
帳戶:user2
密碼:444c02
帳戶:user3
密碼:6b381f
帳戶:user4
密碼:28d8fd

shell編程之for語句實戰案例

需求:
1. 批量檢查當前教室主機是否在線

#!/bin/bash
. /etc/init.d/functions
ip=192.168.7. 
for i in {100..150} 
do
        if ping -c 1 -w 1 $ip$i &>/dev/null;then
                echo -n "$ip$i在線!" 
                success
                echo ""
        else 
                echo -n "$ip$i不在線!" 
                failure
                echo "" 
        fi
done

練習題1:計算100之內的偶數和
[root@ken ~]# cat test13.sh

#!/bin/bash
sum=0
for i in `seq 2 2 100`
do
let sum+=$i
done
echo 「$sum」

執行結果:
[root@ken ~]# bash test13.sh
2550

練習題2:判斷/root目錄下面的文件類型

#!/bin/bash
for i in `ls /root`
do
type1=`ls -ld $i | cut -c 1`
if [ 「$type1」 == 「-」 ];then
echo 「$i是普通文件」
elif [ 「$type1」 == 「l」 ];then
echo 「$i是鏈接文件」
elif [ 「$type1」 == 「d」 ];then
echo 「$i是目錄」
else
echo 「該文件類型沒法識別」
fi
done

執行結果:
[root@ken ~]# bash error.sh
error.sh是普通文件
free_mem是普通文件
ken是目錄
nohup.out是普通文件
passwd是普通文件
t是普通文件
test10.sh是普通文件
test11.sh是普通文件
test12.sh是普通文件
test13.sh是普通文件
test15.sh是普通文件
test16.sh是普通文件
test18.sh是普通文件
test19.sh是普通文件

while語句

條件爲真就進入死循環;條件爲假就退出循環
格式:while list; do list; done
while 條件表達式; do
命令
done

實例1:

#!/bin/bash
N=0
while [ $N -lt 5 ]; do 
      let N++ 
      echo $N
done

# bash test.sh 
1
2
3
4
5

當條件表達式爲 false 時,終止循環。

實例2:條件表達式爲 true,將會產生死循環

#!/bin/bash 
while [ 1 -eq 1 ]; do 
      echo "yes" 
done

也能夠條件表達式直接用 true:
#!/bin/bash 
while true; do 
      echo "yes" 
done

死循環有什麼做用那?
能夠用來後臺運行檢測腳本,以下是是一個檢測腦裂的腳本
咱們只須要在命令行中輸入 nohup bash naolie.sh & 便可在後臺持續運行該腳本

例子1:持續檢測內存剩餘量,並每隔1分鐘輸出至一個文件中

[root@ken ~]# cat test15.sh
#!/bin/bash
while true
do
mem=`free -h | grep 「Mem」 | cut -d 「M」 -f 4 | tr -d 」 「`
echo 「$(date 「+%F %T」) $mem」 >> /root/free_mem
sleep 2
done

執行結果:
[root@ken ~]# tail -f free_mem
2019-05-31 11:39:11 736
2019-05-31 11:39:13 736
2019-05-31 11:39:15 736
2019-05-31 11:39:17 736
2019-05-31 11:39:19 736
2019-05-31 11:39:21 736
2019-05-31 11:39:23 736

例子2:持續檢測內存剩餘量,並每隔1分鐘輸出至一個文件中,並放在後臺運行
1.&
[root@ken ~]# bash test15.sh &
這種寫法關閉終端以後腳本退出

  1. nohup
    [root@ken ~]# nohup bash test15.sh &
    這種寫法終端關閉沒有影響
    關掉腳本:
    ps aux

要想使用 while 循環逐行讀取 a.txt 文件,有三種方式:

方式 1:

#!/bin/bash
cat ./a.txt | while read LINE; do
        echo $LINE
done

方式2:

#!/bin/bash 
while read LINE; do 
        echo $LINE
done < ./a.txt

方式3:
exec < ./a.txt # 讀取文件做爲標準輸出
while read LINE; do
echo $LINE
done

與 while 關聯的還有一個 until 語句,它與 while 不一樣之處在於,是當條件表達式爲 false 時才循環,實際使用中比較少,這裏再也不講解。

#!/bin/bash
n=0 
until [ $n -eq 5 ] 
do 
        let n++ 
        echo "$n" 
done

break和continue語句

break 是終止循環。
continue 是跳出當前循環。

示例 1:在死循環中,知足條件終止循環

#!/bin/bash
N=0
while true; do 
    let N++
        if [ $N -eq 5 ]; then 
                  break 
             fi
    echo $N
done

# bash test.sh 1
2
3
4

裏面用了 if 判斷,並用了 break 語句,它是跳出循環。與其關聯的還有一個 continue 語句,它是跳出本次循環。

示例 2:舉例子說明 continue 用法

#!/bin/bash
N=0
while [ $N -lt 5 ]; do 
      let N++
        if [ $N -eq 3 ]; then 
            continue 
        fi
    echo $N
done

# bash test.sh
1
2
4

當變量 N 等於 3 時,continue 跳過了本次循環,沒有執行下面的 echo。

注意:continue 與 break 語句只能循環語句中使用。
[root@ken-node1 ~]# cat test.sh

#!/bin/bash
st=0
while true
do 
    let st++
    if [ $st -eq 5 ];then 
      continue 
    elif [ $st -eq 10 ];then 
          break
    else 
          echo "$st" 
    fi

done
[root@ken-node1 ~]# bash test.sh 1
2
3
4
6
7
8
9

break和continue語句

兩個語句只能用在循環語句中!
break 是終止循環。
continue 是跳出當前循環。

例子1:break
[root@ken ~]# cat test19.sh

#!/bin/bash
num=1
while true
do
let num++
if [ $num -eq 5 ];then
break
fi
echo 「$num」
done

執行結果:
[root@ken ~]# bash test19.sh
2
3
4

例子2:continue
[root@ken ~]# cat test20.sh

#!/bin/bash
num=0
while true
do
let num++
if [ $num -eq 5 ];then
continue
fi
echo 「$num」
done

執行結果:
[root@ken ~]# bash test20.sh | head
1
2
3
4
6
7
8
9
10
11

實際用法:

#!/bin/bash
while true
do
num=`ss -tnl | grep 「80」 | wc -l`
if [ $num -eq 0 ];then
systemctl restart nginx
if [ $? -ne 0 ];then
echo 「`date ‘+%F %T’` 152.136.127.116騰訊雲主機web服務宕機,技術流ken請儘快上線修復!」 | mail -s 「152.136.127.116騰訊雲主機 web宕機」 1614833188@qq.com
exit
else
echo 「`date ‘+%F %T’` 152.136.127.116騰訊雲主機 web宕機已自動恢復」 | mail -s 「152.136.127.116騰訊雲主機 web宕機恢復」 1614833188@qq.com
continue
fi
fi
done

case語句

case 語句通常用於選擇性來執行對應部分塊命令。
case 模式名 in 模式 1)
  命令
  ;;
模式 2)
  命令
  ;; *)
  不符合以上模式執行的命令
esac
每一個模式必須以右括號結束,命令結尾以雙分號結束,最後一個模式不須要添加;;。

示例1:根據位置參數匹配不一樣的模式

#!/bin/bash case $1 in 
start)
  echo "start." 
        ;;
stop)
  echo "stop." 
       ;;
restart)
  echo "restart." 
        ;; 
*)
  echo "Usage: $0 {start|stop|restart}" esac

# bash test.sh
Usage: test.sh {start|stop|restart}

# bash test.sh start
start.

# bash test.sh stop
stop.

# bash test.sh restart
restart。

實例2:

#!/bin/bash
case $1 in
[0-9])
  echo "match number."
  ;;
[a-z])
  echo "match letter."
  ;;
'-h'|'--help')
  echo "help"
  ;;
*)
  echo "Input error!"
  exit
esac

# bash test.sh 1
match number.

# bash test.sh a
match letter.

# bash test.sh -h
help

# bash test.sh --help
help

模式支持的正則有:*、?、[ ]、[.-.]、|。後面有章節單獨講解 Shell 正則表達式。

shell編程高級實戰

實戰1:寫一個猜數字的小遊戲

要求:

1. 猜對退出
2. 數字隨機
3. 使用體驗佳

#!/bin/bash
clear
num=`echo $RANDOM`
count=0
while true
do
        let count++
        read -p "pls enter a num you guess:" guessnum
        if [ $guessnum -lt $num ]; then
                echo "the num is so smaller!"
        elif [ $guessnum -gt $num ];then
                echo "the num is so bigger!"
        elif [ $guessnum -eq $num ];then
                echo "right!wonderful! " 
                break
        else
                echo "good bye"
                exit
        fi
done

echo -e "\033[36myou guess $count times\033[0m" #-e容許對下面列出的加反斜線轉義的字符進行解釋.

實戰2:檢測當前教室在線IP地址

要求:

1.顯示美觀

#!/bin/bash
. /etc/init.d/functions
ip=172.20.10.
for i in {1..255}
do
        if ping -c 1 $ip$i &>/dev/null ;then
                echo -n "$ip$i"    #-n表示不輸出行尾的換行符
                success
                echo ""
        else
                echo -n "$ip$i"
                failure
                echo ""
        fi
done

實戰3:檢查軟件包是否安裝

要求:

1.用戶輸入軟件名便可進行查詢

#!/bin/bash
read -p "pls enter a softname:" softname
if rpm -q $softname &>/dev/null ;then
        echo "the $softname is already installed"
else
        echo "the $softname" is not installed
fi

實戰4:打印九九乘法表

#!/bin/bash
for i in `seq 9`
do
        for a in `seq 9`
        do
                if [ $a -le $i ];then
                        echo -n "$a*$i=$(($i*$a)) "
                fi
        done
        echo ""
done

補充練習題

1.實現簡單計算器(加減乘除)

#!/bin/bash
read -p "請輸入第一個數字:" a
read -p "請輸入運算符[+-*/]:" b
read -p "請輸入第二個數字:" c
if [ -n "$a" -a -n "$b" -a -n "$c" ];then
        if [ "$b" == "+" ];then
                echo "$a+$c=$(($a+$c))"
        elif [ "$b" == "-" ];then
                echo "$a-$c=$(($a-$c))"
        elif [ "$b" == "*" ];then
                echo "$a*$c=$(($a*$c))"
        elif [ "$b" == "/" ];then
                echo "$a/$c=$(($a/$c))"
        else
                echo "請輸入+—*%"
        fi
else
        echo "請按照要求輸入內容!"
fi

2. 批量建立100個以數字開頭的文件,並每隔一秒鐘輸出到終端

#!/bin/bash
for i in {1..100}
do
        touch ${i}.txt
        echo "${i}.txt"
        sleep 1
done

3.動態持續監測本機linux系統內存剩餘量(僅顯示數值),並在終端輸出

#!/bin/bash
while true
do
        mem=`free -h | grep "Mem" | cut -d "M" -f 4 | tr -d " "`
        echo $mem
        sleep 1

done

課後練習題

寫一個腳本: 實現自動化一鍵部署NFS服務器端和客戶端
第二個腳本:實現批量化檢測當前教室主機在線情況,在線主機保存至一個文件中
第三個腳本:實現批量化建立100個用戶,並建立8位隨機密碼,且可登錄
第四個腳本:找出系統中含有某個關鍵詞的文件,並輸出到終端,關鍵詞用戶輸入指定
第五個腳本:批量判斷當前目錄下全部文件類型

補充:shell練習題

1. 每一秒鐘輸出/root下的文件至屏幕
2. 打印出包含某個關鍵詞的文件(關鍵詞執行腳本時接收)
3. 統計系統中以.sh結尾的文件總大小,輸出結果以kb爲單位

參考答案:

#!/bin/bash
for file in `ls /root`
do
        echo $file
        sleep 1
done
#!/bin/bash
key=$1
for file in `find / -type f`
do
        grep "$key" $file &>/dev/null
        if [ $? -eq 0 ];then
                echo $file
                sleep 1
        fi
done
#!/bin/bash
sum=0
for size in `find /root -name "*.sh" -exec ls -l {} \; | cut -d " " -f 5`
do
        let sum+=$size
done
echo "$((sum/1024))kb"
相關文章
相關標籤/搜索