LinuxShell編程二之使用結(jié)構(gòu)化命令

第十二章:使用結(jié)構(gòu)化命令

本章內(nèi)容

使用if-then語句
嵌套if語句
test命令
復(fù)合條件測(cè)試
使用雙方括號(hào)和雙括號(hào)
case命令

12.1 使用if-then語句

語句格式:

if command
then
command
fi

if command; then
command
fi

語句說明:bash shell的if語句會(huì)運(yùn)行if后面的那個(gè)命令滚局,如果該命令的退出狀態(tài)碼是0(該命令執(zhí)行成功)燕锥,則位于then部分的命令就回被執(zhí)行。如果不是0毙沾,則不執(zhí)行then部分的命令,繼續(xù)執(zhí)行腳本中的下一個(gè)命令宠页。fi語句表示if-then語句到此結(jié)束左胞。

編寫test1.sh腳本

#!/bin/bash
# testing the if statement
if pwd
then
    echo It worked
fi

編寫test2.sh腳本

#!/bin/bash
# testing a bad command
if IamNotaCommand
then 
    echo "It worked"
fi
echo "We are outside the if statement"

編寫test3.sh腳本

#!/bin/bash
if grep $testuser /etc/passwd
then 
    echo "This is my first command"
    echo "This is my second command" 
    echo "I can even put in other commands besides echo:"
    ls -a /home/$testuser/.b*
fi

12.2 if-then-else語句

語句格式

if command
then 
command
else
command
fi

語句說明:當(dāng)if語句中的命令返回退出狀態(tài)碼為0時(shí),then部分中的命令會(huì)被執(zhí)行举户;當(dāng)狀態(tài)碼不為0時(shí)烤宙,else部分中的命令會(huì)被執(zhí)行。

編寫test4.sh腳本

#!/bin/bash
# testing multiple commands in the then section

testuser=nosuchuser

if grep $testuser /etc/passwd
then 
    echo "This is my first command"
    echo "This is my second command" 
    echo "I can even put in other commands besides echo:"
    ls -a /home/$testuser/.b*
else
    echo "The user $testuser does not exist on this system."
fi

12.3 嵌套if

要檢查/etc/passwd文件中是否存在某個(gè)用戶以及該用戶的目錄是否尚在俭嘁,可以使用嵌套的if-then語句躺枕。嵌套的if-then語句位于主if-then-else語句的else代碼塊中。

語句格式

if command1
then
commands
elif command2
then
more commands
else
moreandmore commands
fi

語句說明:先執(zhí)行command1供填,返回狀態(tài)碼為0時(shí)拐云,執(zhí)行commands,從elif到fi之間的命令則跳過捕虽。當(dāng)command1返回狀態(tài)碼不為0時(shí)慨丐,則執(zhí)行command2,command2的返回狀態(tài)碼為0泄私,則執(zhí)行more commands房揭;不為0,則執(zhí)行moreandmore commands晌端。

編寫test5.sh腳本

#!/bin/bash
# testing nested ifs - use elif

testuser=nosuchuser

if grep $testuser /etc/passwd
then
    echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
    echo "The user $testuser dose not exist on this system."
    echo "However,$testuser has a directory"
else
    echo "The user $testuser dose not exist on this system."
    echo "And,$testuser dose not have a directory"
fi

竅門:在elif語句中捅暴,緊跟其后的else語句屬于elif代碼塊。它們并不屬于之前的if-then代碼塊咧纠。

可以將多個(gè)elif語句串起來

if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 5
fi

12.4 test命令

命令格式:test condition

命令說明:如果test命令中列出的條件成立蓬痒,test命令就回返回0,否則返回非零的狀態(tài)碼漆羔,這樣就可以結(jié)合if-then語句使用梧奢。

語句格式

if test condition
then
commands
fi

語句說明:如果test命令的condition部分為空時(shí)狱掂,它會(huì)返回非零的退出狀態(tài)碼。

語句格式

if [ condition ]
then
commands
fi

語句說明:bash shell提供的另一種測(cè)試方法亲轨,第一個(gè)方括號(hào)之后和第二個(gè)方括號(hào)之前必須加一個(gè)空格趋惨。

test命令可以判斷三類條件

數(shù)值比較
字符串比較
文件比較

12.4.1 數(shù)值比較

test命令的數(shù)值比較功能

n1 -eq n2:檢查n1是否等于n2
n1 -gen2:檢查n1是否大于或等于n2
n1 -gt n2:檢查n1是否大于n2
n1 -le n2:檢查n1是否小于或等于n2
n1 -lt n2:檢查n1是否小于n2
n1 -ne n2:檢查n1是否不等于n2

編寫numberic_test.sh腳本

#!/bin/bash
value1=10
value2=11
#
if [ $value1 -gt 5 ]
then
    echo "The test value $value1 is greater then 5"
fi
#
if [ $value1 -eq $value2 ]
then
    echo "The values are equal"
else
    echo "The values are different"
fi

bash shell只能處理整數(shù)。如果只是通過echo來顯示浮點(diǎn)數(shù)惦蚊,則沒問題器虾;如果用于數(shù)值比較,則會(huì)出錯(cuò)蹦锋。

編寫floating_point_test.sh腳本

#!/bin/bash
#
value1=5.555
#
echo "The test value is $value1"
#
if [ $value1 -gt 5 ]
then
    echo "The test value $value1 is greater then 5"
fi

12.4.2 字符串比較

字符串比較測(cè)試

str1 = str2:檢查str1是否和str2相同
str1 != str2:檢查str1是否和str2不同
str1 < str2:檢查str1是否比str2姓咨场(使用時(shí)大于符號(hào)注意轉(zhuǎn)義)
str1 > str2:檢查str1是否比str2大(使用時(shí)小于符號(hào)注意轉(zhuǎn)義)
-n str2:檢查str1的長(zhǎng)度是否非0
-z str2:檢查str1的長(zhǎng)度是否為0

1.字符串相等性

編寫test7.sh腳本

#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER = $testuser ]
then
    echo "Welcome $testuser"
else
    echo "This is not $testuser"
fi

編寫test8.sh腳本

#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER != $testuser ]
then
    echo "This is not $testuser" 
else
    echo "Welcome $testuser"  
fi

2.字符串順序

編寫test9.sh腳本

#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ]
then
    echo "$val1 is greater than $val2" 
else
    echo "$val1 is less than $val2"
fi

注意:在進(jìn)行字符串比較時(shí),使用的是標(biāo)準(zhǔn)的ASCII順序莉掂,根據(jù)每個(gè)字符的ASCII數(shù)值來決定排序結(jié)果葛圃,大寫字母被認(rèn)為是小于小寫字母的。但sort命令恰好相反憎妙。

說明:test命令和測(cè)試表達(dá)式使用標(biāo)準(zhǔn)的數(shù)學(xué)比較符號(hào)來表示字符串比較装悲,而用文本代碼(如:-eq,-ge等)來表示數(shù)值比較尚氛。這個(gè)細(xì)微的特性被很多程序員理解反了。如果你對(duì)數(shù)值使用了數(shù)據(jù)運(yùn)算符洞渤,shell會(huì)將它們當(dāng)成字符串值阅嘶,可能無法得到正確的結(jié)果。

3.字符串大小

編寫test10.sh腳本

#!/bin/bash
# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
    echo "The string '$val1' is not empty" 
else
    echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ] 
then
    echo "The string '$val2' is empty"
else
    echo "The string '$val2' is not empty"
fi
#
if [ -z $val3 ] 
then
    echo "The string '$val3' is empty"
else
    echo "The string '$val3' is not empty"
fi

敲門:空的和未初始化的變量會(huì)對(duì)shell腳本測(cè)試造成災(zāi)難性的影響载迄。如果不是很確定一個(gè)變量的內(nèi)容讯柔,最好在將其用于數(shù)值或字符串比較之前先通過-n或-z來測(cè)試一下變量是否含有值。

12.4.3 文件比較

test命令的文件比較功能

-d file:檢查file是否存在并是一個(gè)目錄
-e file:檢查file是否存在
-f file:檢查file是否存在并是一個(gè)文件
-r file:檢查file是否存在并可讀
-s file:檢查file是否存在并非空
-w file:檢查file是否存在并可寫
-x file:檢查file是否存在并可執(zhí)行
-O file:檢查file是否存在并屬當(dāng)前用戶所有
-G file:檢查file是否存在并且默認(rèn)組與當(dāng)前用戶相同
file1 -nt file2:檢查file1是否比file2新
file1 -ot file2:檢查file1是否比file2舊

1.檢查目錄

-d測(cè)試會(huì)檢查指定的目錄是否存在于系統(tǒng)中护昧。如果你打算將文件寫入目錄或是準(zhǔn)備切換到某個(gè)目錄中魂迄,先進(jìn)行測(cè)試總是件好事情

編寫test11.sh腳本

#!/bin/bash
# Look before you leap
#
jump_directory=/home/zc
#
if [ -d $jump_directory ]
then
    echo "The $jump_directory directory exists"
    cd $jump_directory
    ls
else
    echo "The $jump_directory directory dose not exist"
fi

2.檢查對(duì)象是否存在

-e比較允許你的腳本代碼在使用文件或目錄前先檢查它們是否存在

編寫test12.sh腳本

#!/bin/bash
# Check if either a directory or file exists
#
location=$HOME
file_name="sentinel"
#
if [ -e $location ]
then #Directory does exist
    echo "OK on the $location directory."
    echo "Now checking on the file, $file_name."
    #
    if [ -e $location/$file_name ]
    then #File does exist
        echo "OK on the filename"
        echo "Updating Current Date..."
        date >> $location/$file_name
    #
    else #File does not exist
        echo "File does not exist"
        echo "Nothing to update"
    fi
#
else #Directory does not exist
    echo "The $location directory does not exist."
    echo "Nothing to update"
fi

3.檢查文件

-e比較可用于文件和目錄。要確定指定對(duì)象為文件惋耙,必須用-f比較

編寫test12.sh

#!/bin/bash
# check if either a directory or file exists
#
item_name=$HOME
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
    echo "The item, $item_name, does exist."
    echo "But is it a file?"
    echo
    #
    if [ -f $item_name ]
    then #Item is a file
        echo "Yes, $item_name is a file."
    #
    else #Item is not a file
        echo "No, $item_name is not a file."
    fi
#
else #Item does not exist
    echo "The item, $item_name, does not exist."
    echo "Nothing to update"
fi

4.檢查是否可讀

在嘗試從文件中讀取數(shù)據(jù)之前捣炬,最好先測(cè)試一下文件是否可讀,可以使用-r比較測(cè)試

編寫test14.sh腳本

#!/bin/bash
# testing if you can read a file
pwfile=/etc/shadow
#
# first, test if the file exists, and is a file
if [ -f $pwfile ]
then
    # now test if you can read it
    if [ -r $pwfile ]
    then
        tail $pwfile
    else
        echo "Sorry, I am unable to read the $pwfile file"
    fi
else
    echo "Sorry, the file $pwfile does not exist"
fi

5.檢查空文件

使用-s比較來檢查文件是否為空绽榛,當(dāng)-s比較成功時(shí)湿酸,說明文件中有數(shù)據(jù)。

編寫test15.sh腳本

#!/bin/bash
# Testing if a file is empty
#
file_name=$HOME/sentinel
#
if [ -f $file_name ]
then
    if [-s $file_name ]
    then
        echo "The $file_name file exists and has data in it."
        echo "Will not remove this file."
    else
        echo "The $file_name file exists,but is empty."
        echo "Deleting empty file..."
        rm $file_name
    fi
else
    echo "File,$file_name,does not exist."
fi

6.檢查是否可寫

使用-w比較進(jìn)行判斷你對(duì)文件是否有可寫權(quán)限

編寫test16.sh腳本

#!/bin/bash
# check if a file is writable.
#
item_name=$HOME/sentinel
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
    echo "The item, $item_name, does exist."
    echo "But is it a file?"
    echo
    #
    if [ -f $item_name ]
    then #Item is a file
        echo "Yes, $item_name is a file."
        echo "But is it writable?"
        echo
        #
        if [ -w $item_name ]
        then #Item is writable
            echo "Writing current time to $item_name"
            date +$H$M >> $item_name
        #
        else #Item is not writable
            echo "Unable to write to $item_name"
        fi
    #
    else #Item is not a file
        echo "No, $item_name is not a file."
    fi
#
else #Item does not exist
    echo "The item, $item_name, does not exist."
    echo "Nothing to update"
fi

7.檢查文件是否可以執(zhí)行

使用-x比較判斷特定文件是否有執(zhí)行權(quán)限

編寫test17.sh腳本

#!/bin/bash
# testing file execution
#
if [ -x test16.sh ]
then 
    echo "You can run the script:"
    ./test16.sh
else
    echo "Sorry, you are unable to execute the script"
fi

8.檢查所屬關(guān)系

使用-O比較測(cè)試當(dāng)前用戶是否是文件的屬主

編寫test18.sh腳本

#!/bin/bash
# eheck file ownership
#
if [ -O /etc/passwd ]
then 
    echo "You are the owner of the /etc/passwd file"
else
    echo "Sorry, you are not the owner of the /etc/passwd file"
fi

9.檢查默認(rèn)屬組關(guān)系

使用-G比較檢查文件的默認(rèn)組灭美,如果它匹配了用戶的默認(rèn)組推溃,則測(cè)試成功。注:-G比較只會(huì)檢查默認(rèn)組而非用戶所屬的所有組届腐。

編寫test19.sh腳本

#!/bin/bash
# check file group test
#
if [ -G $HOME/testing ]
then
    echo "You are in the same group as the file"
else
    echo  "The file is not owned by you group"
fi

10.檢查文件日期

使用-nt比較判斷一個(gè)文件是否比另一個(gè)文件新铁坎。如果文件較新蜂奸,則文件的創(chuàng)建日期更近。
使用-ot比較判斷一個(gè)文件是否比另一個(gè)文件舊硬萍。如果文件較舊扩所,則文件的創(chuàng)建日期更早。

編寫test20.sh腳本

#!/bin/bash
# testing file dates 
#
if [ test19.sh -nt test18.sh ]
then
    echo "The test19 file is newer than test18"
else
    echo "The test18 file is newer than test19"
fi
if [ test17.sh -ot test19.sh ]
then
    echo "The test17 file is older than the test19 file"
fi

編寫test21.sh腳本

#!/bin/bash
# testing file dates 
#
if [ badfile1 -nt badfile2 ]
then
    echo "The badfile1 file is newer than badfile2"
else
    echo "The badfile2 file is newer than badfile1"
fi

注意:這些命令都沒有檢查文件是否存在襟铭,在使用這些命令之前碌奉,必須先確認(rèn)文件是存在的

12.5 復(fù)合條件測(cè)試

if-then語句允許使用布爾邏輯來組合測(cè)試,格式如下

[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]

竅門:布爾邏輯是一種能夠?qū)⒖赡艿姆祷刂岛?jiǎn)化為TRUE或FALSE的方法

編寫test22.sh腳本

#!/bin/bash
# testing compound comparisons
#
if [ -d $HOME ] && [ -w $HOME/testing ]
then
    echo "The file exists and you can write to it"
else
    echo "I connot write to the file"
fi

12.6 if-then的高級(jí)特性

12.6.1 使用雙括號(hào)

命令格式:(( expression ))
命令說明:使用雙括號(hào)可以在比較過程中使用高級(jí)數(shù)據(jù)表達(dá)式

雙括號(hào)命令符號(hào)

val++:后自增
val--:后自減
++val:先自增
--val:先自減
!:邏輯求反
~:位求反
**:冪運(yùn)算
<<:左位移
>>:右位移
&:位布爾與
|:位布爾或
&&:邏輯與
||:邏輯或

編寫test23.sh腳本

#!/bin/bash
# using double parenthesis
#
var1=10
#
if (( $val1 ** 2 > 90 ))
then
    (( val2 = $val1 ** 2 ))  
    echo "The square of $val1 is $val2"
fi

12.6.2 使用雙方括號(hào)

命令格式:[[ expression ]]
命令說明:在單方括號(hào)的基礎(chǔ)上寒砖,增加了模式匹配
命令注意:并不是所有的shell都支持雙方括號(hào)

編寫test24.sh腳本

#!/bin/bash
# using pattern matching
#
if [[ $USER == z* ]]
then
    echo "Hello $USER"
else
    echo "Sorry,I do not know you"
fi

12.7 case命令

編寫test25.sh腳本

#!/bin/bash
# looking for a possible value
#
if [ $USER = "zc" ]
then
    echo "Welcome $USER"
    echo "Please enjoy your visit"
elif [ $USER = "barbara" ]
then
    echo "Welcome $USER"
    echo "Please enjoy your visit"
elif [ $USER = "testing" ]
then
    echo "Special testing account"
elif [ $USER = "jessica" ]
then
    echo "Do not forget to logout when you're done"
else
    echo "Sorry, you are not allowd here"
fi

命令格式:

      case variable in
      pattern1 | pattern2) commands1;;
      pattern3) commands2;;
      *) commands3;;
      esac

命令說明:case命令會(huì)將指定的變量與不同模式進(jìn)行比較

編寫test26.sh腳本

#!/bin/bash
# using the case command
#
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac

12.8 小結(jié)

結(jié)構(gòu)化命令可以改變shell腳本的正常執(zhí)行流赐劣。最基本的結(jié)構(gòu)化命令是if-then語句。該語句可以根據(jù)一個(gè)執(zhí)行一個(gè)命令的結(jié)果來執(zhí)行其他命令哩都。本章介紹了if-then魁兼、if-then-else、elif漠嵌、case語句咐汞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市儒鹿,隨后出現(xiàn)的幾起案子化撕,更是在濱河造成了極大的恐慌,老刑警劉巖约炎,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件植阴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡圾浅,警方通過查閱死者的電腦和手機(jī)掠手,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狸捕,“玉大人喷鸽,你說我怎么就攤上這事【呐模” “怎么了做祝?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸡岗。 經(jīng)常有香客問我剖淀,道長(zhǎng),這世上最難降的妖魔是什么纤房? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任纵隔,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捌刮。我一直安慰自己碰煌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布绅作。 她就那樣靜靜地躺著芦圾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俄认。 梳的紋絲不亂的頭發(fā)上个少,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音眯杏,去河邊找鬼夜焦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛岂贩,可吹牛的內(nèi)容都是我干的茫经。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼萎津,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼卸伞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锉屈,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤荤傲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后颈渊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弃酌,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年儡炼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片查蓉。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乌询,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出豌研,到底是詐尸還是另有隱情妹田,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布鹃共,位于F島的核電站鬼佣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏霜浴。R本人自食惡果不足惜晶衷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晌纫,春花似錦税迷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哥牍,卻和暖如春毕泌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗅辣。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工撼泛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辩诞。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓坎弯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親译暂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抠忘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容