標籤:linux 函數 shell 指令碼
函數是什嗎?
函數是一些命令的集合,使用一個名稱做代表,稱為函數名稱。函數名稱的命名規則和變數相同。
一旦函數定義好了,執行這個名稱,就好象執行Bash的命令一樣,稱為調用函數。實際上,Bash調用函數時,會執行函數裡的命令地區,執行
完畢,Bash會回到調用函數的下一行繼續執行。
函數的最大作用是可以讓程式模組化。如果Script程式中,需要重複執行某一命令地區,那麼就應當使用函數代表這個地區,一方面可使程式精簡,一方面程式碼頁比較容易維護。
一、函數的用法
1、函數的文法
文法1:
function 函數名稱()
{
命令地區
}
函數名稱與()之間可以直接相連,也可用空格隔開。
文法2:
函數名稱()
{
命令地區
}
關鍵詞function可省略
文法3:
function 函數名稱
{
命令地區
}
如果使用關鍵詞function,函數名稱後的()也可省略
例子:
#!/bin/bash
getline () #定義函數getline,用來定義檔案行數
{
local i=0 #i代表已計算的行數,先歸0。
#local用來設定變數i是getline函數中專有的變數,不影響script其它地方也叫i的函數
while read line
do #使用while迴圈,自變數值$file指定檔案讀取每一行
let ++i #每讀一行 變數i值+1
done < $file #使用轉向輸入,讓read能由$file讀取資料
echo "$file檔案共有$i行" #顯示總行
}
file=$1 #由命令列第一個參數,取得要計算行數的檔案名稱。
getline #調用getline函數
echo "getline 執行完畢" #getline執行完後,回到這裡繼續執行下一指令。
#./script passwd
passwd檔案共有36行
getline執行完畢
在調用函數之前一定要先定義該函數。
unset -f 函數 取消函數
2、函數的結束狀態
執行函數時,函數中最後一個命令的傳回值代表函數的結束狀態。執行函數如果遇到return命令,就立即結束,回到調用函數的下一個命令,此時函數的傳回值為0
#!/bin/bash
getline ()
{
local i=0
while read line
do
let ++i
if (($i > 10));then #判斷是否超過10行
echo "$file檔案大於10行,不再繼續"
return #遇到return命令,立即回到echo$?所在行
#預設傳回值為0,也可指定不同的傳回值,直接在return空格加數字即可
fi
done < $file
echo "$file檔案共有$i行"
}
file=$1
getline
echo $?
echo "getline 執行完畢"
可以根據$?(return 接的數字n )的值執行想要的命令,如上 if[ $? -eq 3 ];then
echo "行數過多,放棄讀取"
else
echo ‘getline執行完畢‘
fi
二、函數與變數的作用範圍。
1、函數的作用範圍
函數僅在定義的shell環境中有效,Bash執行函數時,並不會另外再開啟一個子shell。
如果要傳遞函數給shell環境使用,可以用內建命令export -f函數名稱,這樣此函數就變成了環境變數的一部分(函數型),可供子shell的script調用。
2、變數的作用範圍
如果沒有特別的設定變數的屬性,那麼在Script中自訂的變數稱為全域變數(對此指令碼而言)。作用範圍在整個Script檔案中皆有效。
#!/bin/bash
getline ()
{
local i=0 #這就定義了變數i只在函數getline中有效,變數i和函數外其它叫i的變數完全不一樣。
while read line
do
....
三、位置參數
1、命令列的位置參數
$0 表示指令碼名 $1 表示第一個參數 $2表示第2給參數 $(10)表示第10個參數
$* 代表所有的位置參數,看為一個字串。1.sh a x y則$*為"a x y"
[email protected] 代表所有以空白隔開的參數,各位置串列。 1.ah a x y則[email protected]為"a"、"x"、"y"
$# 位置參數的個數,1.ah a x y則$#的值為3
#!/bin/bash
if [ $# -ne 2 ];then 必須鍵入2個參數,否則錯誤退出
echo "使用方法:./$0 參數1 參數2"
exit 1
fi
2、移動位置參數
Bash的內建命令shift可以往前移動位置參數的值,文法如下:
shift n
n為正整數,代表往前移動的次數。n可以省略不寫代表移動一次。執行 shift n,$(n+1)的值會放入$1
以執行shift命令來說(不指定次數),$2的值放入$1,$3的值放入$2,$4的值放入$3,,,如果一直執行shift(次數>=n),會把所有的位置參數清空
shift 一次清除1個(從$1開始) ,shift 2 一次清除2個
#!/bin/bashecho "\[email protected]的初始值為[email protected]"while shiftdo[ -n "$1" ] && echo "shift 1次,\[email protected]的變化:[email protected]"done執行結果:[[email protected] tmp]# bash 1.sh a b c d e [email protected]的初始值為a b c d eshift 1次,[email protected]的變化:b c d eshift 1次,[email protected]的變化:c d eshift 1次,[email protected]的變化:d eshift 1次,[email protected]的變化:e
3、指定位置參數的值
指定位置參數的值稱為重設(reset),用Bash命令set
#!/bin/bashdeclare -i i=0set 10 20 30 40 50 for p in [email protected] do ((i++)) echo " 第 $i 個位置參數 $$i = $p" #$$目前bash shell的進程編號 done[[email protected] tmp]# bash 2.sh 第 1 個位置參數 3547i = 10 第 2 個位置參數 3547i = 20 第 3 個位置參數 3547i = 30 第 4 個位置參數 3547i = 40 第 5 個位置參數 3547i = 50
一旦用set重設位置參數,其原有的值就會消失,改以新值取代。(無論輸入幾個參數,set設定幾個就是幾個)
如果要一次重設所有參數,使其值為空白,可執行 set --
4、取用命令列的選項和參數
在設計指令碼的時候,往往需要由命令列中取得使用者提供的選項和參數,根據不同的選項,指令碼有不同的處理方式和執行結果。選項的使用方式可以
是單一選項,也可以在選項後方加上準備作用的參數,而且,選項出現的次序並沒有嚴格的要求。
如以下例子:
./script -u jacken -a -h
或改用以下形式
./script -a -u jacken -h
如果要想取得這些選項和參數,使用前述的位置參數也是可以的,不過拿到位置參數後,必須再做許多條件判斷才行,因為選項可能以不同的次序
出現在命令列不同的位置,情況十分複雜。解決這樣的問題,可改用Bash提供的內建命令getopts。
getopts文法如下:
getopts 選項行 選項變數
其中選項行,是由各選項的單一字元組成,如前述例子中用來3個選項,可組合成“u:ah”
如果某一個選項字元後方,接上":" 則表示該選項需要提供一個參數,如這裡的u後面有":"
如果執行指令碼的時候,選項u後方沒有提供額外的參數,那麼Bash就會顯示“option requires an argument --u”的錯誤資訊。
如果不想出現這種錯誤資訊,可在選項行最前面加上":" 如 ":u:ah" 像這樣子,u後邊沒有參數也不會報錯了。
至於選項變數的作用是:
getopts由命令列取得選項,把它放入選項變數中,如果該選項需要額外的參數,參數值會放入OPTARG這個變數中。
例子:
[[email protected] ~]# ./opt.sh -a提供了選項a[[email protected] ~]# ./opt.sh -h提供了選項h[[email protected] ~]# ./opt.sh -a -h提供了選項a提供了選項h[[email protected] ~]# ./opt.sh -u./opt.sh: option requires an argument -- u[[email protected] ~]# ./opt.sh -u hello提供了選項-u和參數:hello[[email protected] ~]# cat opt.sh #!/bin/bash#while getopts u:ah optdo case $opt in u) echo "提供了選項-u和參數:$OPTARG";; a) echo "提供了選項a";; h) echo "提供了選項h";; *) ;; esacdone[[email protected] ~]#
四、建立函數庫
如果某些函數經常出現在設計的script中,可以考慮把這些函數抽出來,集中存成一個檔案,但這個檔案稱為函數庫。
在命名函數時,函數名稱第一個字元使用_(底線),通常這就代表系統用的函數或變數名稱。
在/tmp下建立函數庫mylib1.sh
_getip()
{
local tmp r ip #函數內部使用的變數設為私人
[ -z "$1" ] && return #如果位置參數$1為空白,直接退出
shuzu=() #建立陣列變數shuzu,作為傳回ip字串用,初始值設為空白數組
tmp=$(ifconfig $1 | grep ‘inet addr‘)
r=${tmp/inet addr:/}
ip=${r/Bcast*/}
shuzu=($ip) #將找到的ip設為第一個數組元素,作為函數處理結果的傳回值
}
調用函數資料庫的文法,. /路徑/函數資料庫 .也用source來表示
#!/bin/bash
MYLIB_DIR="/tmp" #設定函數庫預設路徑
if [ ! -d "MYLIB_DIR" ];then
MYLIB_DIR="." #如果預設路徑不存在就設為目前的目錄
fi
. $MYLIB_DIR/mylib1.sh #調用函數庫mylib1.sh
_getip eth0 #執行_getip傳入的參數是網路介面的名稱eth0
ip=${shuzu[0]} #取出代表函數執行結果的陣列變數shuzu的第一個元素,設值給變數ip
if [ -n "$ip" ];then #判斷$ip是否為空白,-z 為空白 -n不為空白
echo "主機ip是:$ip"
else
echo "找不到IP"
fi
本文出自 “Welcome To Linux World” 部落格,請務必保留此出處http://linuxnote.blog.51cto.com/9876511/1641215
Linux Shell之七 函數應用