1. 程式人生 > >Linux Shell指令碼程式設計提高(12)

Linux Shell指令碼程式設計提高(12)

實際上Shell是一個命令直譯器,它解釋由使用者輸入的命令並且把它們送到核心,不僅如此,Shell有自己的程式語言用於對命令的編輯,它允許使用者編寫由shell命令組成的程式.Shel程式語言具有普通程式語言的很多特點,比如它也有迴圈結構和分支控制結構等,用這種程式語言編寫的Shell程式與其他應用程式具有同樣的效果,下面我們會介紹Shell-Script的編寫.



Shell 條件判斷

◆按檔案型別判斷◆

1.使用 [] 來執行判斷,並使用echo $? 判斷執行結果

[[email protected] ~]# ls
lyshark.log  passwd.awk

[
[email protected]
~]# [ -e ./lyshark.log ] [[email protected] ~]# echo $? #返回0表示檔案 ./lyshark.log 存在 0 [[email protected] ~]# [ -e ./shar ] #返回1表示檔案 ./shar 不存在 [[email protected] ~]# echo $? 1

2.我們可以結合之前所學的 && 和 || 實現判斷後輸出判斷結果

[[email protected] ~]# ls
lyshark.log  passwd.awk

[
[email protected]
~]# [ -e ./lyshark.log ] && echo "check ok" || echo "None" check ok [[email protected] ~]# [ -e ./shar ] && echo "check on" || echo "None" None

◆按檔案許可權判斷◆

1.使用 -r 判斷檔案是否可讀,和可執行

[[email protected] ~]# ls
lyshark.log passwd.awk

[[email protected] ~]# [ -r ./lyshark.log ] && echo "check ok" || echo "None"
check ok

[
[email protected]
~]# [ -x ./lyshark.log ] && echo "check ok" || echo "None" None [[email protected] ~]# [ -r ./lyshark.log ] && [ -x ./lyshark.log ] && echo "可讀,可執行" || echo "可讀,不可執行" || echo "不可讀,不可執行" 可讀,不可執行

◆兩檔案之間的比較◆

1.通過 -ef 判斷是否是相同的I節點

[[email protected] ~]# ls -li
total 0
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark_ln.log
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark.log

[[email protected] ~]# [ ./lyshark.log -ef lyshark_ln.log ] && echo "ok" || echo "no"
ok

◆數值之間的比較◆

1.比較兩數字,大小關係

[[email protected] ~]# [ 23 -ge 24 ] && echo "23 >= 24 " || echo "23 <= 24"
23 <= 24

[[email protected] ~]# [ 30 -ge 24 ] && echo "30 >= 24 " || echo "30 <= 24"
30 >= 24

◆字串之間的比較◆

1.字串之間的比較例子,字串是否為空

[[email protected] ~]# name=LyShark
[[email protected] ~]# age=""
[[email protected] ~]# unset sex

[[email protected] ~]# [ -z "$name" ] && echo "字串空" || echo "不為空"
不為空

[[email protected] ~]# [ -z "$age" ] && echo "字串空" || echo "不為空"
字串空

[[email protected] ~]# [ -z "$sex" ] && echo "字串空" || echo "不為空"
字串空

2.兩個字串相等比較

[[email protected] ~]# x=100
[[email protected] ~]# y=200
[[email protected] ~]# z=100

[[email protected] ~]# [ "x" == "y" ] && echo "yes" || echo "no"
no
[[email protected] ~]# [ "$x" == "$y" ] && echo "yes" || echo "no"
no

[[email protected] ~]# [ "$x" == "$z" ] && echo "yes" || echo "no"
yes

◆多重條件判斷◆

1.邏輯與:判斷變數x不為空,並且x大於20

[[email protected] ~]# declare -i x=10
[[email protected] ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
no
[[email protected] ~]# declare -i x=30
[[email protected] ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
yes

2.邏輯非:判斷x變數不為空,或!取反

[[email protected] ~]# declare -i x=30

[[email protected] ~]# [ -n "$x" ] && echo "yes" || echo "no"
yes

[[email protected] ~]# [ ! -n "$x" ] && echo "yes" || echo "no"
no


IF條件判斷

if、then、else語句用於判斷給定的條件是否滿足,並根據測試條件的真假來選擇相應的操作.if/else僅僅用於兩分支判斷,多分支的選擇時需要用到if/else語句巢狀、if/elif/else和case多分支選擇判斷結構.

IF結構例子: 一個就簡單的單分支結構.測試條件後如果沒有";"則then語句要換行.

#!/bin/sh
echo "Please input a Number:"
read Num
 
if [ "$Num" -lt 15 ]
then
    echo "$Num <= 15"
fi

IF/IF-ELSE結構: 一個雙分支結構,如下執行刪除檔案,成功返回then是否返回else.

#!/bin/sh
 
echo "Please input the file which you want to delete:"
read file
 
if rm -f "$file"
then
  echo "Delete the file $file  sucessfully!"
else
  echo "Delete the file $file failed!"
fi

IF/ELSE巢狀: 可同時判斷三個或三個以上條件,但要注意if與else配對關係,else語句總是與它上面最近的未配對的if配對.

#!/bin/bash
#提示使用者輸入分數(0-100)
echo "Please Input a integer(0-100): "
read score

#判斷學生的分數類別
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
   echo "The score what you input is not integer or the score is not in (0-100)."
else
     if [ "$score" -ge 90 ]
     then
         echo "The grade is A!"
     else
          if [ "$score" -ge 80 ]
          then
              echo "The grade is B!"
          else
               if [ "$score" -ge 70 ]
              then
                   echo "The grade is C!"
              else
                   if [ "$score" -ge 60 ]
                   then
                        echo "The grade is D!"
                   else
                        echo "The grade is E!"
                   fi
              fi
         fi
    fi
fi

IF/ELIF/ELSE結構: if/else巢狀在程式設計中很容易漏掉then或fi產生錯誤,而且可讀性很差,因此引入if/elif/else結構針對某一事件的多種情況進行處理,fi只出現一次,可讀性也提高了.

#!/bin/bash  
 
echo "Please Input a integer(0-100): "
read score
 
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
    echo "The score what you input is not integer or the score is not in (0-100)."
elif [ "$score" -ge 90 ]
then
    echo "The grade is A!"
elif [ "$score" -ge 80 ]
then
    echo "The grade is B!"
elif [ "$score" -ge 70 ]
then
    echo "The grade is C!"
elif [ "$score" -ge 60 ]
then
    echo "The grade is D!"
else
    echo "The grade is E!"
fi

例項1: 通過單分支判斷磁碟是否已滿.

[[email protected] ~]# cat if.sh

#!/bin/bash

ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
        echo -e "/dev/sda1 is full !!"
fi

例項2: 通過多分支判斷磁碟是否已滿.

[[email protected] ~]# cat if.sh
#!/bin/bash

ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
        echo -e "/dev/sda1 is full !"
else
        echo -e "/dev/sda1 is not full !"
fi

例項3: 多分支判斷小例子.

[[email protected] ~]# cat if.sh
#!/bin/bash

read -p "輸入一個數字:" num

if [ "$num" -gt "100" ]
then
        echo -e "這個數大於100"
elif [ "$num" -lt "100" ]
then
        echo -e "這個數小於100"
elif [ "$num" -eq "100" ]
then
        echo -e "這個數等於100"
fi

例項4: 判斷輸入的年份是否是潤年(潤年條件:1、能被4整除,但不能被100整除的年份.2、能被100整除,又能被400整除的年份)

#!/bin/sh
  
echo "Please Input a year: "
read year
 
let "n1=$year % 4"
let "n2=$year % 100"
let "n3=$year % 400"
if [ "$n1" -ne 0 ]
then
    leap=0
elif [ "$n2" -ne 0 ]
then
    leap=1
elif [ "$n3" -ne 0 ]
then
    leap=0
else
    leap=1
fi


CASE分支結構

case結構變數值依次比較,遇到雙分號則跳到esac後的語句執行,沒有匹配則指令碼將執行預設值*"後的命令,直到"';;"為止.case的匹配值必須是常量或正則表示式.

#!/bin/bash

read -p "輸入一個符號:" temp

case $temp in

        "-print")
                echo -e "您執行了print函式"
        ;;
        "-save")
                echo -e "您執行了save函式"
        ;;
        "-help")
                echo -e "您執行了help函式"
        ;;
        *)
                echo -e "您執行了其他操作"
        ;;
esac


FOR迴圈結構

Shell程式設計中迴圈命令用於特定條件下決定某些語句重複執行的控制方式,有三種常用的迴圈語句:for、while和until.while迴圈和for迴圈屬於"當型迴圈",而until屬於"直到型迴圈",迴圈控制符:break和continue控制流程轉向.

列表FOR迴圈: 迴圈列印資料分別從1遍歷到5.

do和done之間的命令稱為迴圈體,執行次數和list列表中常數或字串的個數相同.for迴圈,首先將in後list列表的第一個常數或字串賦值給迴圈變數,然後執行迴圈體,以此執行list,最後執行done命令後的命令序列.

#!/bin/bash
 
for tmp in {1..5}
do
     echo "Hello, Welcome $tmp times"
done

FOR迴圈累加: 通過FOR迴圈累加列印資料.

通過i的按步數2不斷遞增,計算sum值為2500.同樣可以使用seq命令實現按2遞增來計算1~100內的所有奇數之和,for i in $(seq 1 2 100),seq表示起始數為1,跳躍的步數為2,結束條件值為100.

#!/bin/bash
sum=0
 
for i in {1..100..2}
do
    let "sum+=i"
done

echo "sum=$sum"

FOR迴圈遍歷目錄: 通過for迴圈顯示當前目錄下所有的檔案.

#!/bin/bash
 
for file in $( ls )
#for file in *
do
   echo "file: $file"
done

不帶列表FOR: 由使用者制定引數和引數的個數,與上述的for迴圈列表引數功能相同.

#!/bin/bash

echo "number of arguments is $#"
echo "What you input is: "

for argument
do
    echo "$argument"
done

C風格FOR迴圈: 也被稱為計次迴圈.

#!/bin/bash
for((integer = 1; integer <= 5; integer++))
do
    echo "$integer"
done

例項1: 通過for迴圈列印1-10.

[[email protected] ~]# cat for.sh
#!/bin/bash

for temp in `seq 1 10`
do
        echo -e "列印資料: $temp"
done

例項2: 通過for迴圈計算1-100的累加和.

[[email protected] ~]# cat for.sh
#!/bin/bash

declare -i sum=0

for temp in `seq 1 100`
do
        sum=$sum+$temp
done

echo -e "從1+到100的結果是: $sum"

例項3: 從列表中選擇資料.

[[email protected] ~]# cat for.sh
#!/bin/bash

for temp in 1 3 5 7 9
do
        echo -e "列印: $temp"
done

[[email protected] ~]# bash for.sh
列印: 1
列印: 3
列印: 5
列印: 7
列印: 9

例項4: 讀取檔案內容並列印.

[[email protected] ~]# cat for.sh
#!/bin/bash

world=`cat /etc/passwd`
for temp in $world
do
        echo -e "列印: $temp"
done

WHILE 迴圈

也稱為前測試迴圈語句,重複次數是利用一個條件來控制是否繼續重複執行這個語句.為了避免死迴圈,必須保證迴圈體中包含迴圈出口條件即表示式存在退出狀態為非0的情況.

計數控制: 指定了迴圈的次數500,初始化計數器值為1,不斷測試迴圈條件i是否小於等於100.在迴圈條件中設定了計數器加2來計算1~100內所有的奇數之和.

#!/bin/bash
 
sum=0
 
i=1
 
while(( i <= 100 ))
do
     let "sum+=i"
     let "i += 2"   
done
 
echo "sum=$sum"

結束標記控制的while迴圈: 設定一個特殊的資料值(結束標記)來結束while迴圈.

#!/bin/bash
 
echo "Please input the num(1-10) "
read num
 
while [[ "$num" != 4 ]]
do 
   if [ "$num" -lt 4 ]
   then
        echo "Too small. Try again!"
        read num
   elif [ "$num" -gt 4 ]
   then
         echo "To high. Try again" 
         read num
   else
       exit 0
    fi
done 
 
echo "Congratulation, you are right! "

標誌控制的while迴圈: 使用使用者輸入的標誌值來控制迴圈的結束(避免不知道迴圈結束標誌的條件).

#!/bin/bash
 
echo "Please input the num "
read num
 
sum=0
i=1
 
signal=0
 
while [[ "$signal" -ne 1 ]]
do
    if [ "$i" -eq "$num" ]
    then 
       let "signal=1"
       let "sum+=i"
       echo "1+2+...+$num=$sum"
    else
       let "sum=sum+i"
       let "i++"
    fi
done

命令列控制的while迴圈: 使用命令列來指定輸出引數和引數個數,通常與shift結合使用,shift命令使位置變數下移一位($2代替$1、$3代替$2,並使$#變數遞減),當最後一個引數顯示給使用者,$#會等於0,$*也等於空.

#!/bin/bash

echo "number of arguments is $#"
echo "What you input is: "
 
while [[ "$*" != "" ]]
do
    echo "$1"
    shift
done

while計算: 通過while迴圈,計算1-100的累加和.

[[email protected] ~]# cat while.sh
#!/bin/bash

declare -i x=0
declare -i num=0

while [ "$x" -lt "100" ]
do
        x=$x+1
        num=$num+$x
done

echo -e "從1-100結果是: $num"

[[email protected] ~]# bash while.sh
從1-100結果是: 5050


UNTIL 迴圈

until命令和while命令類似,while能實現的指令碼until同樣也可以實現,但區別是until迴圈的退出狀態是不為0,退出狀態是為0(與while剛好相反),即whie迴圈在條件為真時繼續執行迴圈而until則在條件為假時執行迴圈.

#!/bin/bash
 
i=0
 
until [[ "$i" -gt 5 ]]    #大於5
do
    let "square=i*i"
    echo "$i * $i = $square"
    let "i++"
done
#!/bin/bash
 
for (( i = 1; i <=9; i++ ))
do
    
    for (( j=1; j <= i; j++ ))
    do
        let "temp = i * j"     
        echo -n "$i*$j=$temp  "
     done 
     
     echo ""   #output newline
done
#!/bin/bash

i=0

until [[ "$i" -gt 5 ]]    #大於5

do

    let "square=i*i"

    echo "$i * $i = $square"

    let "i++"

done


跳出語句(break,continue)

break: 在for、while和until迴圈中break可強行退出迴圈,break語句僅能退出當前的迴圈,如果是兩層迴圈巢狀,則需要在外層迴圈中使用break.

#!/bin/bash
 
sum=0
for (( i=1; i <= 100; i++))
do 
    let "sum+=i"
 
    if [ "$sum" -gt 1000 ]
    then
        echo "1+2+...+$i=$sum"
        break
    fi
done

continue: 在for、while和until中用於讓指令碼跳過其後面的語句,執行下一次迴圈.continue用於顯示100內能被7整除的數.

#!/bin/bash
 
m=1
for (( i=1; i < 100; i++ ))
do
    let "temp1=i%7"         #被7整除
 
    if [ "$temp1" -ne 0 ]
    then
        continue
    fi
    
    echo -n "$i  "
    
    let "temp2=m%7"          #7個數字換一行
    
    if  [ "$temp2" -eq 0 ]
    then
        echo ""
    fi
    
    let "m++"
done


SELECT 語句

select結構從技術角度看不能算是迴圈結構,只是相似而已,它是bash的擴充套件結構用於互動式選單顯示,功能類似於case結構比case的互動性要好.

[[email protected] ~]# cat select.sh
#!/bin/bash

echo -e "請選擇系統型別?"

select var in "Linux" "GNU HURD" "FreeBSD" "Other";
do
        if [ $var == "Linux" ]
        then
                echo -e "您的系統是Linux"
        elif [ $var == "FreeBSD" ]
        then
                echo -e "您的系統是FreeBSD"
        fi
break
done
[[email protected] ~]# bash select.sh
請選擇系統型別?
1) Linux
2) GNU HURD
3) FreeBSD
4) Other

#? 1
您的系統是Linux
#!/bin/bash

declare -a serial
serial=(1 2 3 4)
PS3="Enter a number: "


select var in "a" "b" "c" "d"
do
    if ! echo ${serial[@]} | grep -q $REPLY
        then
                echo "please enter [1-4]."
                continue
    fi

        echo "your anwser is: $var"
        break
done

[[email protected] ~]# bash select.sh
1) a
2) b
3) c
4) d
Enter a number: 1
your anwser is: a


FUNCTION 函式

[[email protected]alhost ~]# cat function.sh
#!/bin/bash

function my_print()
{
        echo -e "------------------------"
        echo -e "hello world"
        echo -e "------------------------"
        return "127"
}


my_print
echo $?

[[email protected] ~]# bash function.sh
------------------------
hello world
------------------------
127

推薦一個shell部落格:
https://blog.csdn.net/taiyang1987912/article/details/38929069