shell快速入門

本文下載

shell快速入門

參考文檔

shell從入門到放棄(上)

shell從入門到放棄(中)

shell從入門到放棄(下)

朱雙印的個人日誌-shell

shell的基本概念

shell是什麼

Shell本身是一個用C語言編寫的程序,它是用戶使用Unix/Linux的橋樑,用戶的大部分工作都是通過Shell完成的。Shell既是一種命令語言,又是一種程序設計語言。作爲命令語言,它交互式地解釋和執行用戶輸入的命令;作爲程序設計語言,它定義了各種變量和參數,並提供了許多在高級語言中才具有的控制結構,包括循環和分支。      

它雖然不是Unix/Linux系統內核的一部分,但它調用了系統核心的大部分功能來執行程序建立文件並以並行的方式協調各個程序的運行。因此,對於用戶來說,shell是最重要的實用程序,深入瞭解和熟練掌握shell的特性極其使用方法,是用好Unix/Linux系統的關鍵。

shell有哪些

Unix/Linux上常見的Shell腳本解釋器有bash、sh、csh、ksh等,習慣上把它們稱作一種Shell。我們常說有多少種Shell,其實說的是Shell腳本解釋器。

bash

bash是Linux標準默認的shell,bash由Brian Fox和Chet Ramey共同完成,是Bourne Again Shell的縮寫,內部命令一共有40個。

 

Linux使用它作爲默認的shell是因爲它有諸如以下的特色:

可以使用類似DOS下面的doskey的功能,用方向鍵查閱和快速輸入並修改命令。

自動通過查找匹配的方式給出以某字符串開頭的命令。

包含了自身的幫助功能,你只要在提示符下面鍵入help就可以得到相關的幫助。

sh

sh 由Steve Bourne開發,是Bourne Shell的縮寫,sh是Unix標準默認的shell。

ash

ash shell 是由Kenneth Almquist編寫的,Linux中佔用系統資源最少的一個小shell,它只包含24個內部命令,因而使用起來很不方便。

csh

csh 是Linux比較大的內核,它由以William Joy爲代表的共計47位作者編成,共有52個內部命令。該shell其實是指向/bin/tcsh這樣的一個shell,也就是說,csh其實就是tcsh。

ksh

ksh 是Korn shell的縮寫,由Eric Gisin編寫,共有42條內部命令。該shell最大的優點是幾乎和商業發行版的ksh完全兼容,這樣就可以在不用花錢購買商業版本的情況下嘗試商業版本的性能了。

 

注意: bash是 Bourne Again Shell 的縮寫,是linux標準的默認shell ,它基於Bourne shell,吸收了C shell和Korn shell的一些特性。bash完全兼容sh,也就是說,用sh寫的腳本可以不加修改的在bash中執行。

編譯語言與解釋型語言

編譯語言

很多傳統的程序設計語言,例如C、C++和Java,都是編譯型語言。這類語言需要預先將我們寫好的源代碼(source code)轉換成目標代碼(object code),這個過程被稱作“編譯”。

 

運行程序時,直接讀取目標代碼(object code)。由於編譯後的目標代碼(object code)非常接近計算機底層,因此執行效率很高,這是編譯型語言的優點

 

但是,由於編譯型語言多半運作於底層,所處理的是字節、整數、浮點數或是其他機器層級的對象,往往實現一個簡單的功能需要大量複雜的代碼。例如,在C++裏,就很難進行“將一個目錄裏所有的文件複製到另一個目錄中”之類的簡單操作。

解釋型語言

解釋型語言也被稱作“腳本語言”。執行這類程序時,解釋器(interpreter)需要讀取我們編寫的源代碼(source code),並將其轉換成目標代碼(object code),再由計算機運行。因爲每次執行程序都多了編譯的過程,因此效率有所下降

 

使用腳本編程語言的好處是,它們多半運行在比編譯型語言還高的層級,能夠輕易處理文件與目錄之類的對象;缺點是它們的效率通常不如編譯型語言。不過權衡之下,通常使用腳本編程還是值得的:花一個小時寫成的簡單腳本,同樣的功能用C或C++來編寫實現,可能需要兩天,而且一般來說,腳本執行的速度已經夠快了,快到足以讓人忽略它性能上的問題。腳本編程語言的例子有awk、Perl、Python、Ruby與Shell。

shell腳本入門

shell腳本是什麼

shell腳本就是命令的堆積。但是很多不命令不具有冪等性,需要用程序邏輯來判斷運行條件是否滿足,以避免運行中產生錯誤;

冪等性:就是用戶對於同一操作發起的一次請求或者多次請求的結果是一致的

運行shell腳本

 (1) 賦予執行權限,並直接運行此程序文件;

chmod +x  test.sh

. /test.sh

當以這種方式運行腳本時:

我們在第一行的bash運行了命令。隨後生成了子進程test.sh。在子進程中運行test.sh。

此時,test.sh不能繼承bash中定義的本地變量。

 (2) 直接運行解釋器,以腳本文件爲參數;

bash  test.sh

       -n:檢測腳本是否正確,但不執行

       -x:執行腳本,並輸出執行過程

--posix:改變bash的行爲,使其符合Posix 1003.2規定的標準。

當以這種方式運行腳本時,同上,只是生成的子進程是bash

 (3)sh運行腳本

相當於打開了bash的POSIX標準模式,即bash --posix

sh是bash的“子集”

當以這種方式運行腳本時,同上,只是生成的子進程是sh

(4)source運行腳本

source test.sh

相當於:

. ./ test.sh #.空格./ test.sh

當以這種方式運行腳本時:

沒有生成子進程,直接在bash裏運行了test.sh。此時可以繼承bash的本地變量。這裏的source也可以理解爲將test.sh文件中的內容包含到當前文件或進程中。

解釋器(頭文件)

shell腳本的第一行(即頭文件),是解釋器程序文件的路徑,用於指明解釋運行當前腳本代碼的解釋器;

n  #!/bin/bash

n  #!/bin/tcsh

n  #!/usr/bin/python3

n  #!/usr/bin/perl

shell的變量

定義變量

定義本地變量

定義變量時,變量名不加美元符號($),如:

myUrl="http://zhaoyongtao.blog.51cto.com/"

myNum=100

注意,變量名和等號之間不能有空格。同時,變量名的命名須遵循如下規則:

l  首個字符必須爲字母(a-z,A-Z)。

l  中間不能有空格,可以使用下劃線(_)。

l  不能使用標點符號。

l  不能使用bash裏的關鍵字(可用help命令查看保留關鍵字)。

重複定義

對某個變量名進行重複定義,後一次定義會覆蓋前一次定義

只讀變量

使用 readonly 命令可以將變量定義爲只讀變量,只讀變量的值不能被改變。

#!/bin/bash

 

myUrl="http://zhaoyongtao.blog.51cto.com/"

readonly myUrl

myUrl=https://blog.51cto.com/

上面這個腳本嘗試更改只讀變量,執行時就會報錯

命令行定義

readonly var=value

只讀變量只對當前bash生效。如果想讓其可以繼承,可以定義環境只讀變量:

export readonly var=value

定義環境變量

使用export關鍵字定義環境變量

export var=value

或是先定義本地變量,在聲明爲環境變量

var=value

export var

declare定義

使用declare也可以聲明一個變量

declare abc=123 #聲明變量abc的值爲123

-i:聲明×××變量

-x:聲明環境變量。相當於export環境變量

-r:聲明只讀變量

 

使用變量

使用一個定義過的變量,只要在變量名前面加美元符號($)即可,如:

your_name="kim"

echo $your_name

echo ${your_name}

變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界。推薦使用變量時,都用加花括號的寫法

刪除變量

使用 unset 命令可以刪除變量。語法:

unset variable_name

變量被刪除後不能再次使用;unset 命令不能刪除只讀變量

變量類型

運行shell時,會同時存在三種變量:

1) 本地變量

本地變量只在當前bash進程終有效,對當前shell進程外的其他shell進程,包括當shell的子shell進程均無效

1)局部變量

局部變量只對當前函數或代碼段有效。

如果在腳本範圍爲存在一個全局變量var(即一個函數外有一個全局變量)。則腳本中的同名var變量會覆蓋全局變量。

如果在函數中使用local定義同名var變量local var= ,則函數中的var變量不會覆蓋全局變量var。

2)全局變量

2) 環境變量

所有的程序,包括shell啓動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候shell腳本也可以定義環境變量。

3) shell變量

shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行

特殊變量

在shell中,某些包含其他字符的變量有特殊含義,這樣的變量被稱爲特殊變量。

特殊變量列表

變量

含義

$0

當前腳本的文件名

$n

傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2

$#

傳遞給腳本或函數的參數個數。

$*

傳遞給腳本或函數的所有參數。

$@

傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同,下面將會講到。

${@:起點}表示由起點開始(包括起點),取得後面的所有位置參數

${@:起點:個數}:表示由起點開始(包括起點),取得指定個數的位置參數

$?

上個命令的退出狀態,或函數的返回值。

$$

當前Shell進程ID。對於 Shell 腳本,就是這些腳本所在的進程ID。

$*$@的區別

$* 和 $@ 都表示傳遞給函數或腳本的所有參數。

假設某腳本有參數:a,b,c,d,e

這樣看上去都是一樣的

$*= a b c d

"$*"= a b c d

$@= a b c d

"$@"= a b c d

然後我們分別遍歷它們:

for var in $@/$*/“$@”/“$*”

do

echo "$var"

done

不被雙引號(" ")包含時

都以"$1" "$2" … "$n" 的形式輸出所有參數。

結果都爲:

a

b

c

d

被雙引號(" ")包含時

"$*" 會將所有的參數合爲一個字符串,以"$1 $2 … $n"的形式輸出所有參數;

遍歷結果爲:

a b c d

這證明所有參數在一個變量中

"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。

遍歷結果不變

變量的替換

轉義字符

如果表達式中包含特殊字符,Shell 將會進行替換。例如,在雙引號中使用變量就是一種替換,轉義字符也是一種替換。

#!/bin/bash

 

a=10

echo -e "Value of a is $a \n"  # -e 表示對轉義字符進行替換,不適用-e則原樣輸出

echo能使用的轉義字符有:

轉義字符

含義

\\

反斜槓

\a

警報,響鈴

\b

退格(刪除鍵)

\f

換頁(FF),將當前位置移到下頁開頭

\n

換行

\r

回車

\t

水平製表符(tab鍵) 

\v

垂直製表符

命令替換

命令替換是指Shell可以先執行命令,將輸出結果暫時保存,在適當的地方輸出。

`command`  #注意是反引號

例如:

#!/bin/bash

 

DATE=`date`

echo "Date is $DATE"

變量替換

變量替換可以根據變量的狀態(是否爲空、是否定義等)來改變它的值。

#!/bin/bash

 

echo ${var:-"Variable is not set"}

echo "1 - Value of var is ${var}"

 

echo ${var:="Variable is not set"}

echo "2 - Value of var is ${var}"

 

unset var

echo ${var:+"This is default value"}

echo "3 - Value of var is $var"

 

var="Prefix"

echo ${var:+"This is default value"}

echo "4 - Value of var is $var"

 

echo ${var:?"Print this message"}

echo "5 - Value of var is ${var}"

 

形式

說明

${var}

變量本來的值

${var:-word}

如果變量 var 爲空或已被刪除(unset),那麼返回 word,但不改變 var 的值。

${var:=word}

如果變量 var 爲空或已被刪除(unset),返回word,將   var 的值設置爲 word。var不爲空,則值不變

${var:?message}

如果變量 var 爲空或已被刪除(unset),那麼將消息 message 送到標準錯誤輸出,可以用來檢測變量 var 是否可以被正常賦值。
  若此替換出現在Shell腳本中,那麼腳本將停止運行。

如果變量 var 被定義,無返回,var值不變

${var:+word}

如果變量 var 被定義,返回var的值,不改變 var 的值

如果變量 var 未定義,返回word,不改變 var 的值

 

shell的運算符

Shell支持很多運算符,包括:Shell算數運算符、關係運算符、布爾運算符、字符串運算符等

算數運算符

算術運算符

u  +,-

u  *, / 

u  %:取餘

u  **:次方

算術運算格式

(1) let  VAR=算術表達式 let var=$a+$b。只支持整數運算

(2) VAR=$[算術表達式] var1=$[$a+$b] 。只支持整數運算

(3) VAR=$((算術表達式)) var3=$(($a+$b)) 。只支持整數運算

(4) VAR=$(expr $ARG1 $OP $ARG2) expr 2 + 2  #變量和運算符間必須有空格,且*號使用時,要用\轉義。只支持整數運算

(5)bc命令。支持小數運算echo "2.5*3.4" |bc

關係運算符

-eq 檢測兩個數是否相等,相等返回 true。

-ne 檢測兩個數是否相等,不相等返回 true。

-gt  檢測左邊的數是否大於右邊的,如果是,則返回 true。

-ge 檢測左邊的數是否大等於右邊的,如果是,則返回 true。

-lt   檢測左邊的數是否小於右邊的,如果是,則返回 true。

-le   檢測左邊的數是否小於等於右邊的,如果是,則返回 true。

-gt>

-gt與-lt只能比較兩個數字的大小。而>和小於可以根據ASCII碼比較字符串的大小。

[  “a”\> “b” ]  # 單中括號需要轉義。字母和括號間有空格

[[  “a” > “b” ]] # 雙中括號不需轉義。字母和括號間有空格

布爾運算符

運算符

說明

舉例

!

非運算,表達式爲 true 則返回 false,否則返回 true。

[ ! false   ] 返回 true。

-o

或運算,有一個表達式爲 true 則返回 true。

[ $a -lt   20 -o $b -gt 100 ] 返回 true。

||

或運算。但同有些-o區別


-a

與運算,兩個表達式都爲 true 才返回 true。

[ $a -lt   20 -a $b -gt 100 ] 返回 false。

&&

與運算,但同-a有些區別


-a&&

-a是單大括號[-a]

&&是雙大括號[[&&]]。也可以是 [判斷1] && [判斷2]

&&相比-a多了短路與特性:

cmd1 && cmd2 # 若cmd1爲真則執行cmd2。爲假則不執行

-o&&

-o是單大括號[-a]

||是雙大括號[[||]]。也可以是 [判斷1] || [判斷2]

||相比-o多了短路或特性:

cmd1 || cmd2 # 若cmd1爲真則不執行cmd2。爲假則執行

擴展:

cmd1 && cmd2 || cmd3 #若cmd1位真則執行cmd2,爲假則執行cmd3

 

字符串運算符

運算符

說明

舉例

=

檢測兩個字符串是否相等,相等返回 true。

[ $a = $b   ] 返回 false。

!=

檢測兩個字符串是否相等,不相等返回 true。

[ $a != $b   ] 返回 true。

-z

檢測字符串長度是否爲0,爲0返回 true。

[ -z “$a”   ] 返回 false。

-n

檢測字符串長度是否爲0,不爲0返回 true。

[ -n “$a”   ] 返回 true。

str

檢測字符串是否爲空,不爲空返回 true。

[ $a ] 返回 true。

[][[]]

在使用-z與-n時,如果是“[]”,需要給變量加上雙引號。“[[]]”則不用加。

在使用”=~”匹配正則表達式時,只能使用“[[]]”

tel=136999

[[ $tel =~ [0-9]{6} ]]

echo $?

0

文件測試運算符


  

操作符

說明

舉例

-b file

檢測文件是否是塊設備文件,如果是,則返回 true。

[ -b $file   ] 返回 false。

-c file

檢測文件是否是字符設備文件,如果是,則返回 true。

[ -b $file   ] 返回 false。

-d file

檢測文件是否是目錄,如果是,則返回 true。

[ -d $file   ] 返回 false。

-f file

檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回   true。

[ -f $file   ] 返回 true。

-p file

檢測文件是否是具名管道,如果是,則返回 true。

[ -p $file   ] 返回 false。

-g file

檢測文件是否設置了 SGID 位,如果是,則返回 true。

[ -g $file   ] 返回 false。

-k file

檢測文件是否設置了粘着位(Sticky Bit),如果是,則返回 true。

[ -k $file   ] 返回 false。

-u file

檢測文件是否設置了 SUID 位,如果是,則返回 true。

[ -u $file   ] 返回 false。

-r file

檢測文件是否可讀,如果是,則返回 true。

[ -r $file   ] 返回 true。

-w file

檢測文件是否可寫,如果是,則返回 true。

[ -w $file   ] 返回 true。

-x file

檢測文件是否可執行,如果是,則返回 true。

[ -x $file   ] 返回 true。

-s file

檢測文件是否爲空(文件大小是否大於0),不爲空返回 true。

[ -s $file   ] 返回 true。

-e file

檢測文件(包括目錄)是否存在,如果是,則返回 true。

[ -e $file   ] 返回 true。

shell的字符串

字符串是shell編程中最常用最有用的數據類型。而在使用字符串時,單引號和雙引號的作用有些不同。

單引號與雙引號

單引號

str='this is a string'

單引號字符串的限制:

1)     單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的;

2)     單引號字串中不能出現單引號(對單引號使用轉義符後也不行)。

雙引號

your_name='qinjx'

str="Hello, I know your are \"$your_name\"! \n"

雙引號的優點:

1)     雙引號裏可以有變量

2)     雙引號裏可以出現轉義字符

簡單操作

拼接字符串

your_name="qinjx"

greeting="hello, "$your_name" !"

greeting_1="hello, ${your_name} !"

echo $greeting $greeting_1

獲取字符串長度

string="abcd"

echo ${#string} #輸出 4

提取子字符串

string="alibaba is a great company"

echo ${string:1:4} # 輸出liba。從變量的第1個字符開始,截取4個字符的長度

echo ${string:0-12:4} # 從倒數第12個字符開始,向後截取4個字符的長度

echo ${string: -12:4} # 從倒數第12個字符開始,向後截取4個字符的長度

echo ${string:0-12:-4} #從倒數第12個字符開始,向後截取所有字符,並刪除最後4個字符

變量設置方式

說明

${string#*關鍵字 }

刪除從左到右遇到的第一個“關鍵字”。及其左側所有字符

${string##*關鍵字 }

刪除從左到右遇到的最後一個“關鍵字”。及其左側所有字符

${string%*關鍵字 }

刪除從右向左遇到的第一個“關鍵字”。及其右側所有字符

${string%%*關鍵字 }

刪除從右向左遇到的最後一個“關鍵字”。及其右側所有字符

${string/舊字符串/新字符串   }

第一個替換

${string//舊字符串/新字符串   }

所有替換

${string/關鍵字}

刪除字符串中的第一個關鍵字

${string//關鍵字}

刪除字符串中的所有關鍵字

${string/#關鍵字}

刪除行首的某個關鍵字

${string/%關鍵字}

刪除行尾的某個關鍵字

 

查找子字符串

string="alibaba is a great company"

echo `expr index "$string" is` #輸出3。

注:expr index "$string" is的含義爲,查找“$string”字符串中“i”或“s”第一次出現的地方。由於i最先出現。所以返回結果爲3

字符串的大小寫轉換

所有字母變大小。加兩個^^

echo ${var^^}

所有字母變小寫。加兩個,,

echo ${var,,}

 

變量替換

數組

定義數組

在Shell中,用括號來表示數組,數組元素用“空格”符號分割開。定義數組的一般形式爲:

array_name=(value1 ... valuen)

例如:

array_name=(value0 value1 value2 value3)

或者

array_name=(

value0

value1

value2

value3

)

還可以單獨定義數組的各個分量:

array_name[0]=value0

array_name[1]=value1

array_name[2]=value2

可以不使用連續的下標,而且下標的範圍沒有限制。

讀取數組

讀取數組元素值的一般格式是:

${array_name[index]}

例如:

valuen=${array_name[2]}

使用@ 或 * 可以獲取數組中的所有元素,例如:

${array_name[*]}

${array_name[@]}

獲取數組長度

獲取數組長度的方法與獲取字符串長度的方法相同,例如:

# 取得數組元素的個數

length=${#array_name[@]}

# 或者

length=${#array_name[*]}

# 取得數組單個元素的長度

lengthn=${#array_name[n]}

shell的條件判斷

if-else

if-fi

if [ expression ] # expression 和方括號([ ])之間必須有空格,否則會有語法錯誤

then

   Statement(s) to be executed if expression is true

fi

if-else-fi

if [ expression ]

then

   Statement(s) to be executed if expression is true

else

   Statement(s) to be executed if expression is not true

fi

if-elif-else-fi

if [ expression 1 ]

then

   Statement(s) to be executed if expression 1 is true

elif [ expression 2 ]

then

   Statement(s) to be executed if expression 2 is true

elif [ expression 3 ]

then

   Statement(s) to be executed if expression 3 is true

else

   Statement(s) to be executed if no expression is true

fi

命令行執行

if ... else 語句也可以寫成一行,以命令的方式來運行,像這樣:

if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;

if ... else 語句也經常與 test 命令結合使用,如下所示:

num1=$[2*3]num2=$[1+5]if test $[num1] -eq $[num2]then echo 'The two numbers are equal!'else echo 'The two numbers are not equal!'fi

test 命令用於檢查某個條件是否成立,與方括號([ ])類似。

case-esac

case ... esac 與其他語言中的 switch ... case 語句類似,是一種多分支選擇結構。

case 語句匹配一個值或一個模式,如果匹配成功,執行相匹配的命令。case語句格式如下:

case 值 in

模式1)

    command1

    command2

    command3

    ;;  #“;;”和break類似,意爲跳到整個case語句的最後

模式2)

    command1

    command2

    command3

    ;;

*)  # “*”號表示無匹配到的值,默認執行什麼

    command1

    command2

    command3

    ;;

esac

for

for 變量 in 列表

do

    command1

    command2

    ...

    commandN

done

列表是一組值(數字、字符串等)組成的序列,每個值通過空格分隔。每循環一次,就將列表中的下一個值賦給變量。
in 列表是可選的,如果不用它,for 循環使用命令行的位置參數

while

while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常爲測試條件。其格式爲:

while command

do

   Statement(s) to be executed if command is true

done

until

until 循環執行一系列命令直至條件爲 true 時停止。until 循環與 while 循環在處理方式上剛好相反。

until command

do

   Statement(s) to be executed until command is true

done

command一般爲條件表達式,如果返回值爲 false,則繼續執行循環體內的語句,否則跳出循環。

break

break命令允許跳出所有循環(終止執行後面的所有循環)。

在嵌套循環中,break 命令後面還可以跟一個整數,表示跳出第幾層循環。例如:

break n  # 表示跳出第 n 層循環。

嵌套循環break的例子,如果 var1 等於 2,並且 var2 等於 0,就跳出循環:

#!/bin/bash

for var1 in 1 2 3

do

    for var2 in 0 5

    do

           if [ $var1 -eq 2 -a $var2 -eq 0 ]

       then

       break 2

    else

       echo "$var1 $var2"

    fi

    done

done

如上,break 2 表示直接跳出外層循環。運行結果:

1 0

1 5

如果使用的是break的話。運行結果:

1 0

1 5

3 0

3 5

continue

continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。

#!/bin/bash

while :

do

    echo -n "Input a number between 1 to 5: "

    read aNum

    case $aNum in

        1|2|3|4|5) echo "Your number is $aNum!"

        ;;

        *) echo "You do not select a number between 1 to 5!"

            continue

            echo "Game is over!"

        ;;

    esac

done

運行代碼發現,當輸入大於5的數字時,該例中的循環不會結束,語句

echo "Game is over!"

永遠不會被執行。

同樣,continue 後面也可以跟一個數字,表示跳出第幾層循環。

shell的函數

定義函數

函數可以讓我們將一個複雜功能劃分成若干模塊,讓程序結構更加清晰,代碼重複利用率更高。像其他編程語言一樣,Shell 也支持函數。Shell 函數必須先定義後使用

Shell 函數的定義格式如下:

function_name () {

    list of commands

    [ return value ]

}

如果你願意,也可以在函數名前加上關鍵字 function:

function function_name () {

    list of commands

    [ return value ]

}

函數的返回值

函數返回值,可以顯式增加return語句;如果不加,會將最後一條命令運行結果作爲返回值。

Shell 函數返回值只能是整數,一般用來表示函數執行成功與否,0表示成功,其他值表示失敗。如果 return 其他數據,比如一個字符串,往往會得到錯誤提示:“numeric argument required”。

如果一定要讓函數返回字符串,那麼可以先定義一個變量,用來接收函數的計算結果,腳本在需要的時候訪問這個變量來獲得函數返回值。

調用函數

調用函數只需要給出函數名,不需要加括號

一個帶有return語句的函數:

#!/bin/bash

funWithReturn(){

    echo "The function is to get the sum of two numbers..."

    echo -n "Input first number: "

    read aNum

    echo -n "Input another number: "

    read anotherNum

    echo "The two numbers are $aNum and $anotherNum !"

    return $(($aNum+$anotherNum))

}

funWithReturn

# Capture value returnd by last command

ret=$?

echo "The sum of two numbers is $ret !"

運行結果:

The function is to get the sum of two numbers...

Input first number: 25

Input another number: 50

The two numbers are 25 and 50 !

The sum of two numbers is 75 !

函數返回值在調用該函數後通過 $? 來獲得。

 

如果你希望直接從終端調用函數,可以將函數定義在主目錄下的 .profile 文件,這樣每次登錄後,在命令提示符後面輸入函數名字就可以立即調用。

嵌套函數

#!/bin/bash

 

# Calling one function from another

number_one () {

   echo "Url_1 is http://zhaoyongtao.blog.51cto.com/"

   number_two

}

 number_two () {

   echo "Url_2 is http://zhaoyongtao.blog.51cto.com/10955972/1773727"

}

 number_one

刪除函數

像刪除變量一樣,刪除函數也可以使用 unset 命令,不過要加上 -f 選項,如下所示:

$unset -f function_name

函數參數

在Shell中,調用函數時可以向其傳遞參數。在函數體內部,通過 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數,當n>=10時,需要使用${n}來獲取參數(如${10})。

另外,還有幾個特殊變量用來處理參數,前面已經提到:

特殊變量

說明

$#

傳遞給函數的參數個數。

$*

顯示所有傳遞給函數的參數。

$@

與$*相同,但是略有區別,請查看Shell特殊變量。

$?

函數的返回值。

#!/bin/bash

funWithParam(){

    echo "The value of the first parameter is $1 !"

    echo "The value of the tenth parameter is ${10} !"

    echo "The amount of the parameters is $# !"  # 參數個數

    echo "The string of the parameters is $* !"  # 傳遞給函數的所有參數

}

funWithParam 1 2 3 4 5 6 7 8 9 34 73

shift剔除參數

使用shift可剔除一個參數。如剔除$1,則$2變$1

-n:一次同時剔除前面n個參數。剔除後,後面的參數自動向前排。

通過剔除的方式,我們可以將${10},變爲$1來引用

shell文件引用

像其他語言一樣,Shell 也可以包含外部腳本,將外部腳本的內容合併到當前腳本。

Shell 中包含腳本可以使用:

. filename #點號(.)和文件名中間有一空格

source filename

推薦用source

注意:被包含腳本不需要有執行權限。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章