Linux Shell編程學(xué)習(xí)筆記

本文是對(duì)Linux shell編程的一個(gè)學(xué)習(xí)比較,共包括如下章節(jié)的內(nèi)容:

  • 概述
  • 基本語(yǔ)法
  • 結(jié)構(gòu)化語(yǔ)句
  • 函數(shù)
  • 小結(jié)

參考資料:一些常見(jiàn)的linux bash命令可參見(jiàn)《Linux常見(jiàn)Shell命令》。

一、概述

(一)基本概念

Linux shell是系統(tǒng)的用戶界面,提供了用戶與內(nèi)核進(jìn)行交互操作的一種接口。它接收用戶輸入的命令并把它送入內(nèi)核去執(zhí)行。

shell既是一種解釋器,也是一種編程語(yǔ)言,我們除了可以在命令行下執(zhí)行單條的shell命令外,如 echo , ls , cpd等命令。我們還可以編寫(xiě)shell程序,shell程序是一種腳本語(yǔ)言,同其它腳本語(yǔ)言一樣,shell程序支持變量、結(jié)構(gòu)化語(yǔ)句等特性,我們可以將代碼保存到腳本文件中,后續(xù)調(diào)用執(zhí)行該腳本。

linux的shell和linux版本一樣,有很多種,常見(jiàn)的如:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)

各種shell支持的命令和編程語(yǔ)言語(yǔ)法是類(lèi)似的,但也有些細(xì)微的差別。這些shell類(lèi)型中,其中最常用的是bash(即Bourne Again Shell),bash因?yàn)橐子煤兔赓M(fèi),Bash 在日常工作中被廣泛使用。同時(shí),Bash 也是大多數(shù)Linux 系統(tǒng)默認(rèn)的Shell。

當(dāng)我們?cè)贚inux系統(tǒng)本機(jī)或遠(yuǎn)程打開(kāi)一個(gè)linux控制臺(tái)后,會(huì)自動(dòng)運(yùn)行默認(rèn)的shell程序,出現(xiàn)交互式界面,我們可以通過(guò)echo $0 來(lái)查看當(dāng)前運(yùn)行的是哪種shell。如下面例子:

$ echo $0
-bash

上面例子顯示,我們使用的是bash類(lèi)型。

在本文,我們介紹的是bash。

(二)shell腳本

下面我們來(lái)看下如何編寫(xiě)和執(zhí)行一個(gè)shell腳本文件。

1、新建一個(gè)文本文件

文件名可以是任意合法的文件名,擴(kuò)展名習(xí)慣為sh,當(dāng)然也可以沒(méi)有擴(kuò)展名。我們這里假設(shè)文件名為test.sh。

文件內(nèi)容如下:

#!/bin/bash
echo hello

上面例子的腳本文件就兩行,第一行是個(gè)特殊語(yǔ)句,#! 是一個(gè)約定的標(biāo)記,它告訴系統(tǒng)這個(gè)腳本需要什么解釋器來(lái)執(zhí)行,即使用哪一種 Shell,我們這里是使用bash。所有的shell腳本都必須有這一行內(nèi)容。

后面的內(nèi)容就可以是命令了,我們這里只有一行命令,即echo命令。這樣執(zhí)行該腳本,會(huì)在控制臺(tái)輸出hello內(nèi)容。

2、設(shè)置可執(zhí)行權(quán)限

腳本要想當(dāng)作可執(zhí)行文件被運(yùn)行,需要設(shè)置權(quán)限,如下方式:

chmod +x ./test.sh

使用chmod命令使test.sh文件變?yōu)榭蓤?zhí)行程序。

3、執(zhí)行

在shell提示符下運(yùn)行 ./test.sh ,就可以執(zhí)行該腳本。

在bash腳本中,除#!這個(gè)外,所有#后面的內(nèi)容都會(huì)被當(dāng)作注釋內(nèi)容,執(zhí)行時(shí)會(huì)被忽略,如下面腳本:

#!/bin/bash
echo hello #輸出hello信息
#定義shell變量
myid=100
#輸出變量?jī)?nèi)容
echo $myid

上面腳本中,第一行#!打頭的用于指定shell類(lèi)型,后面的#都是用來(lái)書(shū)寫(xiě)注釋信息的。

shell腳本程序?qū)嶋H是由一條條的命令和結(jié)構(gòu)化語(yǔ)句組成,我們可以把這一條條的shell命令調(diào)用看作其它編程語(yǔ)言的函數(shù)調(diào)用,另外bash也支持定義函數(shù)。linux系統(tǒng)常見(jiàn)的shell命令可參考《Linux常見(jiàn)Shell命令》。

(三)腳本參數(shù)

在編寫(xiě)shell腳本程序時(shí),很多情況下程序需要獲取一些用戶輸入的信息,這有兩種方式,一種是在腳本中使用read命令,當(dāng)腳本執(zhí)行到read命令時(shí),會(huì)停下等待用戶輸入后才會(huì)繼續(xù)執(zhí)行;但在很多時(shí)候,腳本往往被自動(dòng)執(zhí)行,不適合用戶輸入,這個(gè)可以通過(guò)調(diào)用腳本時(shí)給腳本傳入?yún)?shù)來(lái)實(shí)現(xiàn),這種場(chǎng)景往往更多。

下面我們來(lái)介紹如何給腳本傳參數(shù)。

在執(zhí)行 Shell 腳本時(shí),向腳本傳遞參數(shù),腳本內(nèi)獲取參數(shù)的格式為:$n。n 代表一個(gè)數(shù)字,1 為執(zhí)行腳本的第一個(gè)參數(shù),2 為執(zhí)行腳本的第二個(gè)參數(shù),以此類(lèi)推……。另外$0 為執(zhí)行的文件名。

下面舉例說(shuō)明:

假設(shè)腳本文件名為test.sh,文件內(nèi)容如下:

#!/bin/bash
echo $0
echo $1
echo $2

執(zhí)行如下的命令:

$ ./test.sh tom 20
./test.sh
tom
20

可以看出,我們?cè)谡{(diào)用test.sh傳入了兩個(gè)參數(shù)tom和20,在腳本程序中通過(guò)1和2獲取到傳入的參數(shù),并且通過(guò)$0獲取到文件名。

為了簡(jiǎn)單,本文下面的例子演示沒(méi)有寫(xiě)到腳本文件中進(jìn)行調(diào)用執(zhí)行,而是直接在控制臺(tái)$符號(hào)下進(jìn)行的。

二、基本語(yǔ)法

(一)shell變量

變量是任何一門(mén)編程語(yǔ)言中的基本特性,變量用于保存值。Linux shell同樣支持變量。在shell腳本中,可以創(chuàng)建變量,shell腳本中的變量只在創(chuàng)建它的shell中使用。shell中的變量創(chuàng)建和賦值放在一起,不需要使用任何關(guān)鍵字,只需”變量名=變量值”即可。特別要注意的是,=兩邊不能有空格。

使用變量時(shí),通過(guò)$符號(hào)來(lái)引用。如下面示例:

$ x=hello
$ echo $x
hello
$ y=12
$ echo $y
12

需要注意的是,上面例子中以符號(hào)開(kāi)頭的行,這打頭的符號(hào)是shell終端的提示符,該行語(yǔ)句表示執(zhí)行一條命令。沒(méi)有$開(kāi)頭行的是命令執(zhí)行的輸出內(nèi)容。后面的例子一樣。

上面示例代碼中,第1行定義了變量x,其值為hello。第2行執(zhí)行echo命令在控制臺(tái)輸出變量x的值,可以看出,引用變量時(shí)要在變量名前加$符號(hào)。第3行定義了變量y,第4行調(diào)用echo命令輸出變量y的值。

shell是一種腳本語(yǔ)言,弱類(lèi)型的,定義變量時(shí)不需要聲明數(shù)據(jù)類(lèi)型。賦值給變量的值全部會(huì)當(dāng)作字符串處理。值可以用雙引號(hào)或單引號(hào)括起來(lái),也可以不用(如上面例子沒(méi)有用引號(hào)括起),如下面例子:

$ x="hello"
$ echo $x
hello
$ x='hello"world'
$ echo $x
hello"world

上面例子中,給變量賦值時(shí),值用引號(hào)括起來(lái)。

需要注意的是,在shell中,標(biāo)識(shí)符(如變量名)是區(qū)分大小寫(xiě)的。

(二)環(huán)境變量

Linux下的環(huán)境變量與windows下的的環(huán)境變量類(lèi)似。當(dāng)linux內(nèi)核啟動(dòng)一個(gè)程序時(shí),內(nèi)核會(huì)將一個(gè)包含字符串?dāng)?shù)組的列表傳遞給程序,這個(gè)列表稱為命令執(zhí)行環(huán)境,簡(jiǎn)稱為環(huán)境,以name=value格式保存了一系列名/值對(duì)。

在bash中,我們可以使用這些環(huán)境變量。

linux中的環(huán)境變量分為持久和臨時(shí)的,持久的環(huán)境變量是在文件中保存的,因?yàn)槭浅志没?,所以永久有效;而臨時(shí)的環(huán)境變量只在內(nèi)存中,只針對(duì)當(dāng)前shell會(huì)話有效。

下面我們先看下如何定義臨時(shí)的環(huán)境變量。通過(guò)export命令可以定義環(huán)境變量。如下面例子:

$ export myid=100
$ echo $myid
100

上面例子第一句定義了環(huán)境變量myid,該變量的值為100,注意等號(hào)兩邊不能有空格。使用環(huán)境變量和使用shell變量一樣,用$加前綴引用。

在上一節(jié)我們介紹了shell變量的使用,那與環(huán)境變量有啥區(qū)別呢?我們通過(guò)例子來(lái)說(shuō)明:

$ myid=100
$ echo $myid
100
$ bash
$ echo $myid
$

上面例子,我們先定義了一個(gè)shell變量myid,然后我們?cè)诋?dāng)前會(huì)話下運(yùn)行bash程序(相當(dāng)于啟動(dòng)了一個(gè)子shell),會(huì)發(fā)現(xiàn)在這子shell中,無(wú)法獲取到父shell中定義的變量。

我們看下如果定義成環(huán)境變量會(huì)如何?如下面例子:

$ export myid=100
$ echo $myid
100
$ bash
$ echo $myid
100
$

可以看出,定義成環(huán)境變量后,在子shell中就可以使用。

需要說(shuō)明的是,當(dāng)在控制臺(tái)執(zhí)行一個(gè)shell腳本文件時(shí),相當(dāng)于啟動(dòng)一個(gè)子shell,這意味著無(wú)法在shell文件中引用外部定義的shell變量,但可以使用環(huán)境變量。

下面我們來(lái)看下如何持久化環(huán)境變量,即將環(huán)境變量的設(shè)置信息保存在文件中。Linux中環(huán)境變量包括系統(tǒng)級(jí)和用戶級(jí),系統(tǒng)級(jí)的環(huán)境變量是每個(gè)登錄到系統(tǒng)的用戶都要讀取的系統(tǒng)變量,而用戶級(jí)的環(huán)境變量則是該用戶使用系統(tǒng)時(shí)加載的環(huán)境變量。 所以linux保存環(huán)境變量的文件也分為系統(tǒng)級(jí)和用戶級(jí)的。

持久化環(huán)境變量,很簡(jiǎn)單,只需將export命令寫(xiě)入到相應(yīng)的配置文件中。需要說(shuō)明的是,不同版本的linux系統(tǒng),所使用的配置文件可能不同,而且這些配置文件還存在相互調(diào)用的問(wèn)題。

用戶登陸時(shí),會(huì)先執(zhí)行/etc/profile腳本文件中的命令,為全系統(tǒng)所有用戶建立環(huán)境變量。我們可以在該文件中設(shè)置一些對(duì)所有用戶都有關(guān)的環(huán)境變量。需要注意的是,如果修改了該文件中的內(nèi)容,需要重啟系統(tǒng)才能生效。

每個(gè)用戶特有的環(huán)境變量,在該用戶的主目錄下的腳本中設(shè)置。如.bash_profile腳本文件,該文件會(huì)調(diào)用.bashrc腳本文件,而.bashrc又會(huì)調(diào)用/etc/bashrc腳本文件。我們可以在.bash_profile或.bashrc中設(shè)置本用戶特有的環(huán)境變量。每次打開(kāi)shell,.bash_profile都會(huì)被執(zhí)行。如果修改了.bash_profile或.bashrc文件中的內(nèi)容,需要退出當(dāng)前shell重新打開(kāi)shell才能生效。

用戶主目錄下還有一個(gè)腳本文件.bash_logout,當(dāng)用戶退出當(dāng)前shell時(shí),該腳本會(huì)被執(zhí)行,可以在該腳本中進(jìn)行一些資源釋放操作。

(三)運(yùn)算符與表達(dá)式

表達(dá)式是將常量、變量、運(yùn)算符組合在一起,產(chǎn)生一個(gè)值。在本小節(jié)我們來(lái)介紹算術(shù)運(yùn)算。bash支持的算術(shù)運(yùn)算符和其它語(yǔ)言差不多,包括 +(加)、-(減)、*(乘)、/(整除)、%(取余)

在bash中,與其它語(yǔ)言不同,如下的操作是無(wú)法進(jìn)行算術(shù)運(yùn)算的,如:

$ a=2+3
$ echo $a
2+3
$ a=2 + 3
bash: +: 未找到命令...

上面例子,直接數(shù)字相加不是一個(gè)表達(dá)式,如果+兩邊無(wú)空格,則會(huì)被當(dāng)作一個(gè)字符串;如果+兩邊有空格,則會(huì)報(bào)錯(cuò)。

我們?cè)倏聪拢凶兞繀⑴c的情況,例子如下:

$ a=2
$ b=$a+2
$ echo $b
2+2
$ b=$a + 3
bash: +: 未找到命令...

從執(zhí)行情況看,與常量運(yùn)算差不多,依然無(wú)法進(jìn)行計(jì)算。

在bash中,算術(shù)表達(dá)式需要有些特殊的寫(xiě)法,第一種方式是利用expr表達(dá)式,如下面例子:

$ echo `expr 2 + 2`
4
$ a=3
$ echo `expr $a + 2`
5

也就是說(shuō)要在表達(dá)式前加expr關(guān)鍵字,并將整個(gè)內(nèi)容放在倒引號(hào)之中,這才是一個(gè)合法的算術(shù)表達(dá)式。另外要特別注意的是,運(yùn)算符左右要有空格,沒(méi)有空格就不會(huì)被計(jì)算,如下面例子:

$ echo `expr 2+2`
2+2

可以看出,上面例子+左右無(wú)空格,被當(dāng)作了一個(gè)字符串。這使用起來(lái)比較別扭。

還有一種方式是,使用 $[表達(dá)式] 這樣的方式,如:

$ echo $[3+5]
8

采用$[]方式的好處是,運(yùn)算符,如上面的+左右可以有空格,也可以沒(méi)空格,這個(gè)與其它編程語(yǔ)言一樣,用起來(lái)就不容易出錯(cuò)。

另外使用[]時(shí),如果參與運(yùn)算的有變量,則[]中的變量前面不需要加符號(hào),這樣就與其它編程語(yǔ)言中的算術(shù)表達(dá)式類(lèi)似,如下面例子:

$ a=12
$ echo $[a-4]
8
$ echo $[a*a]
144

通過(guò)內(nèi)置命令let可以將一個(gè)表達(dá)式賦值給一個(gè)變量,變量的值就是表達(dá)式的計(jì)算結(jié)果,如下面例子:

$ let x=12+14
$ echo $x
26

上面例子,通過(guò)內(nèi)置命令let將一個(gè)算術(shù)表達(dá)式賦值給了一個(gè)變量x??梢钥闯?,變量的值就是表達(dá)式的計(jì)算結(jié)果。需要注意的是,=和+兩邊都不能有空格。

從上面幾種算術(shù)表達(dá)式的編寫(xiě)方式看,還是使用$[]格式最好,不需要關(guān)心是否有空格等問(wèn)題。

需要注意的是:標(biāo)準(zhǔn)的bash只支持整數(shù)運(yùn)算,不支持浮點(diǎn)運(yùn)算,如下面例子:

$ echo $[12+12]
24
$ echo $[12+12.5]
-bash: 12+12.5: 語(yǔ)法錯(cuò)誤: 無(wú)效的算術(shù)運(yùn)算符 (錯(cuò)誤符號(hào)是 ".5")

可以看出,上面的表達(dá)式中有浮點(diǎn)數(shù)12.5,會(huì)報(bào)錯(cuò)。如果想要支持浮點(diǎn)運(yùn)算,需要使用特殊的第三方包,這里不再介紹。

(四)字符串連接

連接字符串是個(gè)常見(jiàn)的操作,不同于很多編程語(yǔ)言,通過(guò)+運(yùn)算符可以將字符串連接,在bash中,連接字符串的方式如下:

$ x=hello
$ y=world
$ z=${x}${y}
$ echo $z
helloworld

從上面例子可以看出,連接字符串時(shí),用{}將變量名括起,注意$符號(hào)要放在{}外邊。下面再看一個(gè)將變量與常量連接的例子:

$ x=hello
$ z=${x}world
$ echo $z
helloworld

(五)數(shù)組

bash支持一維數(shù)組,將多個(gè)空格分開(kāi)的值放在()可定義數(shù)組,利用下標(biāo)(從0開(kāi)始)可獲取數(shù)組的中等個(gè)元素。如下面例子:

$ arr=(a b c)
$ echo ${arr[0]}
a
$ echo ${arr[2]}
c

上面例子,先定義了一個(gè)數(shù)組arr,然后利用 ${數(shù)組名[序號(hào)]} 這樣的方式來(lái)獲取數(shù)組中的元素。

我們還可以利用下標(biāo)來(lái)新建元素或往元素中添加元素,如:

myarr[0]=1

上面語(yǔ)句,如果myarr數(shù)組不存在,則會(huì)新建一個(gè)數(shù)組,并添加一個(gè)元素。如果已經(jīng)存在,且指定序號(hào)的元素存在,則會(huì)替換,bash中的元素序號(hào)可以不連續(xù),如:

myarr[5]=2

利用@或*做下標(biāo)可以獲取所有數(shù)組的內(nèi)容,如下面例子:

$ data=( 2 4)
$ echo ${data[*]}
2 4
$ echo ${data[@]}
2 4

獲取數(shù)組長(zhǎng)度的語(yǔ)法是 ${#數(shù)組名{*}},如:

echo ${#data[*]}

三、結(jié)構(gòu)化語(yǔ)句

(一)條件表達(dá)式

條件表達(dá)式主要用于if條件語(yǔ)句和循環(huán)語(yǔ)句中。

bash的條件表達(dá)式有如下寫(xiě)法,一種是使用[]的條件表達(dá)式,如下面例子:

a=3
b=4
if [ $a == $b ]
then
  echo a==b
else
  echo a!=b
fi

上面例子中[]之間是一個(gè)條件表達(dá)式,==是判斷是否相等的運(yùn)算符。需要注意的是,[]內(nèi)部的兩邊必須要有空格,運(yùn)算符==的兩邊也必須要有空格。這是使用bash編寫(xiě)程序比較別扭和需要注意的地方。

下表列出了bash常用的關(guān)系運(yùn)算符,假定變量 a 為 3,變量 b 為 4:

運(yùn)算符 說(shuō)明 舉例
== 檢測(cè)兩個(gè)數(shù)是否相等,相等返回 true。 a ==b 返回false
!= 檢測(cè)兩個(gè)數(shù)是否不相等,相等返回 true。 a !=b 返回true
-eq 檢測(cè)兩個(gè)數(shù)是否相等,相等返回 true。等同于== [ a -eqb ] 返回 false。
-ne 檢測(cè)兩個(gè)數(shù)是否不相等,不相等返回 true。等同于!= [ a -neb ] 返回 true。
-gt 檢測(cè)左邊的數(shù)是否大于右邊的,如果是,則返回 true。 [ a -gtb ] 返回 false。
-lt 檢測(cè)左邊的數(shù)是否小于右邊的,如果是,則返回 true。 [ a -ltb ] 返回 true。
-ge 檢測(cè)左邊的數(shù)是否大于等于右邊的,如果是,則返回 true。 [ a -geb ] 返回 false。
-le 檢測(cè)左邊的數(shù)是否小于等于右邊的,如果是,則返回 true。 [ a -leb ] 返回 true。

bash也支持邏輯運(yùn)算符,對(duì)兩個(gè)布爾值進(jìn)行運(yùn)算,其中 -a 用于“與”運(yùn)算;-o用于“或”運(yùn)算;-o用于“非”運(yùn)算,如下面例子:

a=3
b=4
if [ $a -lt 5 -a $b -gt 2 ]
then
   echo "a 小于 5 且 b 大于 2 "
fi

bash也支持字符串的布爾運(yùn)算。下表列出了常用的字符串運(yùn)算符,假定變量 a 為 "abc",變量 b 為 "efg":

運(yùn)算符 說(shuō)明 舉例
= 檢測(cè)兩個(gè)字符串是否相等,相等返回 true。 [ a =b ] 返回 false。
!= 檢測(cè)兩個(gè)字符串是否相等,不相等返回 true。 [ a !=b ] 返回 true。
-z 檢測(cè)字符串長(zhǎng)度是否為0,為0返回 true。 [ -z $a ] 返回 false。
-n 檢測(cè)字符串長(zhǎng)度是否為0,不為0返回 true。 [ -n "$a" ] 返回 true。
$ 檢測(cè)字符串是否為空,不為空返回 true。 [ $a ] 返回 true。

在shell編程中,經(jīng)常要對(duì)文件進(jìn)行操作。bash提供了很多運(yùn)算符進(jìn)行文件的相關(guān)測(cè)試。相關(guān)運(yùn)算符如下:

  • -e 文件名 如果文件存在則為真
  • ** -r 文件名 如果文件存在且可讀則為真**
  • -w 文件名 如果文件存在且可寫(xiě)則為真
  • -x 文件名 如果文件存在且可執(zhí)行則為真
  • -s 文件名 如果文件存在且至少有一個(gè)字符則為真
  • -d 文件名 如果文件存在且為目錄則為真
  • -f 文件名 如果文件存在且為普通文件則為真
  • -c 文件名 如果文件存在且為字符型特殊文件則為真
  • -b 文件名 如果文件存在且為塊特殊文件則為真

下面看一個(gè)例子:

if [ -e test.txt ]
then
 echo test.txt is  exist
fi

上面代碼測(cè)試了當(dāng)前目錄下是否存在test.txt文件。

除了使用[]來(lái)表示條件表達(dá)式外,還可以使用test命令。test是bash的內(nèi)置命令,test命令用于檢查某個(gè)條件是否成立,它可以進(jìn)行數(shù)值、字符和文件三個(gè)方面的測(cè)試,如果成立(即為真)。如下面例子:

a=3
b=4
if test $a == $b
then
  echo a==b
else
  echo a!=b
fi

對(duì)于數(shù)值判斷,還支持通過(guò)(())來(lái)進(jìn)行條件描述,并支持 > ,>= 等運(yùn)算符,這些運(yùn)算符[]和test命令不支持,如下面例子:

int=1
while(($int<=5))
do
    echo $int
    int=$[int+1]
done

使用(())這種寫(xiě)法,運(yùn)算符,如上面的<=左右是否有空格無(wú)所謂。

(二)if語(yǔ)句

bash中的if條件語(yǔ)句,除細(xì)微的語(yǔ)法細(xì)節(jié)不同外,和c,java語(yǔ)言的if語(yǔ)句基本類(lèi)似。其基本語(yǔ)法格式如下:

if  條件
  then
      命令...
fi

如果條件為真,則會(huì)執(zhí)行then后的命令(可以有1條或多條命令),if語(yǔ)句以fi結(jié)尾。

除 if...then...fi語(yǔ)句外,bash還支持 if ...then...else..fi語(yǔ)句,即當(dāng)if后的條件為真,執(zhí)行then后的語(yǔ)句,否則執(zhí)行else后的語(yǔ)句。

另外還支持 if ..then..[elif ..then]..else..fi 語(yǔ)句,可以有1個(gè)或多了elif語(yǔ)句。

因?yàn)閕f語(yǔ)句的語(yǔ)法和其它編程語(yǔ)言類(lèi)似,上面小節(jié)也有舉例了,所以不再詳細(xì)介紹。

(三)case語(yǔ)句

類(lèi)似c,java中的case語(yǔ)句,用于支持多條件匹配,其語(yǔ)法格式如:

case 值 in
匹配值1)
    command1
    command2
    ...
    commandN
    ;;
...
匹配值n)
    command1
    command2
    ...
    commandN
    ;;
esac

上面語(yǔ)法有如下要求:

1)case和in之間的值可以是常量或變量

2)每個(gè)匹配值后面跟著)右括號(hào)

3)某個(gè)匹配值被匹配,其后的命令被執(zhí)行,直至碰到;; (相當(dāng)于其它語(yǔ)言中的break)。需要說(shuō)明的是,被匹配的到分支,一定要有;;x

4)如果想匹配任意值,匹配值可寫(xiě)成*,一般放到最后

5)最后整個(gè)case語(yǔ)句需要用esac結(jié)尾(即case單詞反過(guò)來(lái)寫(xiě))。

下面我們看一個(gè)具體的例子:

num=2
case $num in
    1)  echo 'num = 1'
    ;;
    2)  echo 'num = 2'
    ;;
    3)  echo 'num = 3'
    ;;
    4)  echo 'num = 4'
    ;;
    *)  echo 'num = other'
    ;;
esac

執(zhí)行上面代碼,發(fā)現(xiàn)會(huì)輸出2.

(四)for循環(huán)

bash支持for循環(huán),有如下用法.

1、遍歷多個(gè)值,如:

$ for v in a b c
> do
> echo $v
> done
a
b
c

上面例子用到了for in do done 四個(gè)關(guān)鍵字,in后面跟的是要遍歷的列表值,for和in之間是用于代表每次循環(huán)元素,執(zhí)行的命令需要位于 do和done之間。

說(shuō)明:上面的for語(yǔ)句有換行時(shí),>是控制臺(tái)自動(dòng)顯示的內(nèi)容。如果是在腳本中編寫(xiě),則沒(méi)有>符號(hào)。也可以寫(xiě)在一行,采用如下格式:

for v in a b c;  do  echo $v; done

2、遍歷數(shù)組

可以用for語(yǔ)句來(lái)遍歷數(shù)組,如下面例子:

$ for v in ${arr[*]}
> do
> echo $v
> done
3
6
12

3、c語(yǔ)言的風(fēng)格

也支持類(lèi)似c語(yǔ)言的for循環(huán)風(fēng)格,如下面例子:

$ for((i=1;i<=5;i++))
> do
> echo $i
> done
1
2
3
4
5

注意,for后面的內(nèi)容是用兩個(gè)小括號(hào)包圍的。

(五)while循環(huán)

類(lèi)似c,java中的while語(yǔ)句,滿足條件執(zhí)行循環(huán)中的內(nèi)容。如下面例子:

int=1
while [ $int -le 5 ]
do
    echo $int
    int=$[int+1]
done

或改為(())的條件寫(xiě)法

int=1
while(( $int<=5 ))
do
    echo $int
    let int=int+1hu
done

注意,while后面的條件表達(dá)式要放在兩個(gè)()之間。

同樣我們可以使用test內(nèi)置命令來(lái)作為條件,如:

int=1
while test $int -le 5
do
    echo $int
    let int=int+1
done

(六)break和continue語(yǔ)句

類(lèi)似c,java中的break和continue,可以跳出循環(huán),或提前結(jié)束本次循環(huán)。下面看具體例子:

int=1
while [ $int -le 5 ]
do
    if (( $int==3 ))
    then
       break
    fi
    echo $int
    int=$[int+1]
done

上面代碼執(zhí)行,只會(huì)輸出1,2信息。

再看一個(gè)continue的例子:

int=0
while [ $int -le 5 ]
do
    int=$[int+1]
    if (( $[int%2]==0 ))
    then       
       continue
    fi
    echo $int
done

上面代碼執(zhí)行,只會(huì)輸出1,3,5信息。

四、函數(shù)

(一)基礎(chǔ)

bash支持定義函數(shù),其語(yǔ)法格式為:

[ function ] 函數(shù)名 ()
{
    命令
    [return 整數(shù)]
}

上面語(yǔ)法有如下特點(diǎn):

1)關(guān)鍵字function可選

2)return語(yǔ)句可選,return后面跟0~255的整數(shù)值,作為函數(shù)返回值。如果無(wú)return語(yǔ)句,則以最后一條命令運(yùn)行結(jié)果作為返回值。

下面我們通過(guò)具體的例子來(lái)說(shuō)明。我們先來(lái)看一個(gè)最簡(jiǎn)單的例子,如:

myfun()
{
  echo "this is a fun"
}

上面定義了一個(gè)函數(shù),函數(shù)名為myfun。

調(diào)用函數(shù)就同調(diào)用shell命令類(lèi)似,注意不像其它語(yǔ)言,調(diào)用時(shí)不能加(),如:

$ myfun
this is a fun

上面在$提示符下直接輸入myfun就是調(diào)用函數(shù)。

(二)函數(shù)的返回值

我們先看下shell命令執(zhí)行的返回值,bash中的每條命令執(zhí)行后都會(huì)有一個(gè)返回值,一般情況下成功返回值為0,出錯(cuò)的話返回值就是一個(gè)非0整數(shù)。命令執(zhí)行的返回值,通過(guò)在命令執(zhí)行后使用$?來(lái)獲取。

如下面例子:

$ ls test.txt
test.txt
$ echo $?
0
$ ls test5.txt
ls: 無(wú)法訪問(wèn)test5.txt: 沒(méi)有那個(gè)文件或目錄
$ echo $?
2
$ ls test.txt
test.txt
$ echo $?
0

從上面例子我們可以看出,先使用ls命令顯示一個(gè)正確的文件后,$?的值為0,這是命令返回結(jié)果;然后用ls命令顯示不存在的文件,ls命令會(huì)報(bào)錯(cuò),這時(shí)$?的值為非零值。

bash函數(shù)的調(diào)用,和執(zhí)行shell命令類(lèi)似,其返回值也是通過(guò)$?來(lái)獲取的,這點(diǎn)與其它編程語(yǔ)言差別很大。

前面我們提到,在函數(shù)中通過(guò)可選的return語(yǔ)句,后面跟0~255的整數(shù)值,作為函數(shù)返回值。如果無(wú)return語(yǔ)句,則以最后一條命令運(yùn)行結(jié)果作為返回值。

下面我們通過(guò)例子來(lái)說(shuō)明:

$ myfun()
> {
>   echo "this is a fun"
>   return 100
> }
$ myfun
this is a fun
$ echo $?
100

上面例子我們先定義了一個(gè)函數(shù)myfun,然后調(diào)用該函數(shù),最后顯示$?的值,這個(gè)值就是myfun函數(shù)中的return后面的值。

下面我們?cè)倏匆粋€(gè)無(wú)return語(yǔ)句的例子,如:

$ myfun()
> {
>   rm other.txt
>   echo hello
> }
$ myfun
rm: 無(wú)法刪除"other.txt": 沒(méi)有那個(gè)文件或目錄
hello
$ echo $?
0

上面例子中定義的myfun函數(shù)中有兩條命令,調(diào)用函數(shù)時(shí),rm命令報(bào)錯(cuò),echo命令正常執(zhí)行,所以調(diào)用函數(shù)后獲取到的$?的值為0。如果我們?cè)囍堰@兩個(gè)命令順序換下,會(huì)發(fā)現(xiàn)$?的值不為0,這里不再具體的演示。

(三)函數(shù)的參數(shù)

Bash的函數(shù)也可以有參數(shù),但參數(shù)的使用方法和別的編程語(yǔ)言有較大差別,c/java等編程語(yǔ)言的函數(shù)參數(shù)是在函數(shù)聲明中定義,而bash函數(shù)的參數(shù)由調(diào)用時(shí)決定。

在調(diào)用bash函數(shù)時(shí),可以向其傳遞參數(shù)。在函數(shù)體內(nèi)部,通過(guò) $n 的形式來(lái)獲取參數(shù)的值,例如,$1表示第一個(gè)參數(shù),$2表示第二個(gè)參數(shù),下面我們通過(guò)例子來(lái)說(shuō)明:

$ myfun()
> {
>   echo $1
>   echo $2
> }
$ myfun hello 2
hello
2

上面代碼中函數(shù)myfun通過(guò)$1和$2引用了兩個(gè)函數(shù)參數(shù),調(diào)用函數(shù)時(shí),傳入了2個(gè)參數(shù),正好對(duì)應(yīng)$1和$2.

如果我們調(diào)用時(shí)不傳入?yún)?shù)值,則函數(shù)內(nèi)的$n的值為空。

結(jié)合前面所學(xué)的,可以看出,給函數(shù)傳遞參數(shù)和給腳本文件傳遞參數(shù)適用方式類(lèi)似。

五、小結(jié)

本文是對(duì)linux shell編程的一個(gè)學(xué)習(xí)總結(jié),linux shell是一種腳本語(yǔ)言,具有腳本語(yǔ)言的一些基本特征,如弱類(lèi)型、解釋執(zhí)行,對(duì)變量、結(jié)構(gòu)化語(yǔ)句的支持等,也有一些差異化的語(yǔ)法特點(diǎn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容