bash shell筆記7 創建函數

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

知識體系:
#創建函數
#使用參數
#共享函數
shell腳本代碼可以封裝在函數內,而函數可以在腳本任意處使用,由此減少大段代碼的重複編寫.

1、基本腳本函數
函數是被賦予名稱的腳本代碼塊,可以在代碼的任意位置使用.當需要調用代碼塊的時候,只需引用代碼塊被賦予的函數名即可.
1.1、創建函數
在bash shell腳本中創建函數可以使用兩種方式:
*關鍵字function,基本格式為:
function name{
commands
}
*()方式:
name() {
commands
}
下面就對這兩種方式舉例創建.
1.2、使用函數
如下採用上面創建函數的兩種方式舉例:
[root@wzp ~]# chmod u x 7.1test
[root@wzp ~]# cat 7.1test
#!/bin/bash
function fun1 {
echo "this is the first function"
}
fun1
fun2() {
echo "this is the second function"
}
fun2
[root@wzp ~]# ./7.1test
this is the first function
this is the second function
這裡頭有兩個函數名:fun1和fun2,對應兩個函數執行后顯示不同結果.
但是有點要注意的是先定義好函數,后才能調用,看個例子先:
[root@wzp ~]# cat 7.1test
#!/bin/bash
function fun1 {
echo "this is the first function"
}
fun1
fun2
fun2() {
echo "this is the second function"
}
[root@wzp ~]# ./7.1test
this is the first function
./7.1test: line 6: fun2: command not found
如上我把fun2放置在定義函數fun2之前就調用,shell是不會回頭來執行的,對於函數fun2就報錯了.


並且還要注意每個函數名唯一,如果重新定義函數,那麼新定義的將取代原先的定義,看例子:
[root@wzp ~]# cat 7.1test
#!/bin/bash
function fun1 {
echo "this is the first function"
}
fun1
fun1() {
echo "this is the second function"
}
fun1
[root@wzp ~]# ./7.1test
this is the first function
this is the second function
例子很簡單,效果也看出來了,我們最好區分出函數名了.

2、返回值
bash shell將函數看成小型腳本,並以退出狀態結束,我們可以通過$?查看三種不同的退出狀態,這一點前面已經講述過了.
2.1、默認退出狀態
我們先來看一個例子:
[root@wzp ~]# cat 7.2test
#!/bin/bash
function fun1 {
echo "this is the first function"
ls -l xx
}
fun1
echo "the exit status is :$?"
[root@wzp ~]# chmod u x 7.2test
[root@wzp ~]# ./7.2test
this is the first function
ls: xx: 沒有那個文件或目錄
the exit status is :2
我們看到函數的退出狀態為2,一條命令執行出錯了.再來看看另外一種情況:
[root@wzp ~]# cat 7.2test
#!/bin/bash
function fun1 {
ls -l xx
echo "this is the first function"
}
fun1
echo "the exit status is :$?"
[root@wzp ~]# ./7.2test
ls: xx: 沒有那個文件或目錄
this is the first function
the exit status is :0
我把函數的兩條命令調換位置執行,可以看到第一條報錯了,然後退出狀態值卻是0.從這點我們發現函數的默認退出狀態是不可靠的.


2.2、使用return命令
return命令可以使用單個整數值來定義函數退出狀態,如下例子:
[root@wzp ~]# cat 7.2test
#!/bin/bash
function cto {
read -p "enter a value:" value
echo "doubling the value"
return $[ $value * 2 ]
}
cto
echo "the new value is $?"
[root@wzp ~]# ./7.2test
enter a value:24
doubling the value
the new value is 48
函數cto將變數$value中用戶輸入的值變成雙倍后,使用命令return命令返回結果,然後用$?顯示該結果.
2.3、使用函數輸出
對於命令輸出可以捕獲並存放到shell變數中,函數的輸出也可以捕獲並放到shell變數中,看例子:
[root@wzp ~]# chmod u x 7.3test
[root@wzp ~]# cat 7.3test
#!/bin/bash
ceo () {
read -p "please input a value:" value
echo $[ $value * 2 ]
}
result=`ceo`
echo "the result is : $result"
[root@wzp ~]# ./7.3test
please input a value:13
the result is : 26
通過定義函數后,把函數輸出賦予給變數,這裡使用反引號.

3、在函數中使用變數
如下講述shell腳本函數內外變數處理方法.
3.1、向函數傳遞參數
bash shell將函數作為小型腳本處理,函數可以使用標準參數環境變數來表示命令行傳遞給函數的參數,先看如下例子:
[root@wzp ~]# cat 7.3test
#!/bin/bash
function cio {
if [ $# -eq 0 ] || [ $# -gt 2 ]
then
echo -1
elif [ $# -eq 1 ]
then
echo $[ $1 $1 ]
else
echo $[ $1 * $2 ]


fi
}
echo "##############1##############"
echo -n "adding 10 and 15 :"
value=`cio 10 15`
echo $value
echo "##############2##############"
echo -n "adding just one num of 10:"
value=`cio 10`
echo $value
echo "##############3##############"
echo -n "adding no num:"
value=`cio`
echo $value
echo "##############4##############"
echo -n "adding three num 10 20 30 :"
value=`cio 10 20 30`
echo $value
[root@wzp ~]# ./7.3test
##############1##############
adding 10 and 15 :150
##############2##############
adding just one num of 10:20
##############3##############
adding no num:-1
##############4##############
adding three num 10 20 30 :-1
先通過$#來判斷參數個數,然後針對個數的不同執行不同的算術運算.通過把參數數目傳遞給函數去運算,把運行結果顯示出來.
還有點注意的,函數為自己的參數值使用專用的參數環境變數,函數無法從腳本命令行直接訪問腳本參數值,也就是說函數不識別運行腳本時後面附帶的參數值.如果要調用,在使用函數時手工傳遞這些數據,我們來看個例子:
[root@wzp ~]# cat 7.3test
#!/bin/bash
bad () {
echo $[ $1 $2 ]
}
if [ $# -eq 2 ]
then
value=`bad`
echo "the result is : $value"
else
echo "please input two parameters"
fi
[root@wzp ~]# ./7.3test
please input two parameters
[root@wzp ~]# ./7.3test 1 2
./7.3test: line 3: : syntax error: operand expected (error token is " ")
the result is :


函數不認識1和2這兩個$1、$2,就是函數使用的變數不同於腳本主代碼的變數,我們在使用函數的使用手工附加,改成如下:
[root@wzp ~]# cat 7.3test
#!/bin/bash
bad () {
echo $[ $1 $2 ]
}
if [ $# -eq 2 ]
then
value=`bad $1 $2`
echo "the result is : $value"
else
echo "please input two parameters"
fi
[root@wzp ~]# ./7.3test
please input two parameters
[root@wzp ~]# ./7.3test 8 16
the result is : 24
哈哈,要的就是這個結果,value=`bad $1 $2`是關鍵語句!!!
3.2、在函數中處理變數
這裡要提及一個作用域的概念,表示說變數的可見區域.函數內定義的變數和普通變數有不同的作用域,腳本外部定義的變數要覆蓋函數內定義的變數.函數使用兩個類型的變數:
*全局變數
*局部變數
1》全局變數
全局變數是shell腳本內處處有效的變數,默認情況下腳本中定義的變數都是全局變數,而默認定義的變數在函數內部也可以正常訪問的.例子:
[root@wzp ~]# cat 7.3test
#!/bin/bash
fun () {
value=$[ $value * 2 ]
}
read -p "please input the value:" value
fun
echo "the new value is : $value"
[root@wzp ~]# ./7.3test
please input the value:12
the new value is : 24
對於$value是在函數外部定義的,並且是在外部賦值,當調用給函數fun的時候,該變數在函數中也是有效的,這是全局變數的作用體現.
2》局部變數
對於函數內部使用的變數則是局部變數,而在聲明變數的時候只要在前面多一個local關鍵字即可,先看下例子:


[root@wzp ~]# cat 7.3test
#!/bin/bash
function cfo {
local temp=$[ $value 5 ]
result=$[ $temp 2 ]
}
temp=8
value=10
cfo
echo "the result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
else
echo "temp is smaller"
fi
[root@wzp ~]# ./7.3test
the result is 17
temp is smaller
對於這樣的結果,可以分析如下:返回$result的結果是從函數中得到的,那麼勢必採用函數內部的temp變數,而函數內部的$temp變數賦予值後為15,則顯示result的值為15 2=17.這一點沒什麼好質疑的!但是當temp和result進行大小比較的時候,就直接採用全局變數的值,而跟函數內部定義的temp無關了,這也是local定義內部函數的作用體現了.
這裡我們順便把變數的值取出來看看:
[root@wzp ~]# cat 7.3test
#!/bin/bash
function cfo {
local temp=$[ $value 5 ]
result=$[ $temp 2 ]
}
temp=8
value=10
cfo
echo "the result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
echo "temp=$temp ; result=$result"
else
echo "temp is smaller"
echo "temp=$temp ; result=$result"
fi
[root@wzp ~]# ./7.3test
the result is 17
temp is smaller
temp=8 ; result=17
我只是多加了兩個echo "temp=$temp ; result=$result",就為了把temp和result這兩個變數顯示出來,我們看到,執行函數后,temp的值沒變,函數中局部定義了temp,還是8;可是value的值通過函數運算后是有效生成的,附加后是17.

4、創建庫
函數在單個腳本中有助於減少代碼量,如果多個腳本碰巧使用相同的函數可以通過創建函數的庫文件,然後再不同腳本中引用該庫文件.這種方法,要創建公共庫文件,如下:
[root@wzp ~]# cat funcs
function ceo {
echo $[ $1 $2 ]
}
function cfo {
echo $[ $1 * $2 ]
}
接下來把如上庫文件調用進腳本文件.然後問題在於如果把這個庫文件作為普通腳本文件運行,那麼這些函數不會出現在腳本文件中,看如下例:
[root@wzp ~]# chmod u x funcs
[root@wzp ~]# chmod u x 7.41test
[root@wzp ~]# chmod u x 7.42test
[root@wzp ~]# cat 7.41test
#!/bin/bash
./funcs
result=`ceo 12 24`
echo "the result is $result"
[root@wzp ~]# ./7.41test
./7.41test: line 3: ceo: command not found
the result is
可以看到調用庫文件失敗了,問題就處在於通過./執行庫函數是不可行的.
解決辦法是通過點符號符在shell腳本中運行庫文件腳本,即為source命令,其格式是:
. ./xx 把例子修改如下:
[root@wzp ~]# cat 7.41test
#!/bin/bash
. ./funcs
result=`ceo 12 24`
echo "the result is $result"
[root@wzp ~]# cat 7.42test
#!/bin/bash
. ./funcs
result=`cfo 12 5`
echo "the result is $result"
[root@wzp ~]# ./7.41test
the result is 36
[root@wzp ~]# ./7.42test
the result is 60
我們看到了滿意的結果,關鍵在於通過. ./點符號符來腳本能以調用庫文件的函數,這裡頭是把腳本文件和庫文件放置於同一目錄,為了確保路徑問題的可靠性可使用絕對路徑.

5、在命令行使用函數
有時候想直接在命令行下使用函數也是可以的,在命令行下使用函數有兩種方法,分別如下:
1、將函數定義在一行命令中:
[root@wzp ~]# function 51cto { echo $[ $1 / $2 ]; }
[root@wzp ~]# 51cto 100 20
5
上面這種方法在命令的結尾處加分號,shell知道命令在哪裡分開.
2、使用多行命令定義函數:
[root@wzp ~]# function 51ceo {
> echo $[ $1 * $2 ]
> }
[root@wzp ~]# 51ceo 3 8
24
通過次提示符輸入更多命令,在函數末尾處使用大括弧,shell就知道了定義函數結束,這種方法就不用使用分號了.

本文出自 「twenty_four」 博客,請務必保留此出處http://twentyfour.blog.51cto.com/945260/525126





[火星人 ] bash shell筆記7 創建函數已經有609次圍觀

http://coctec.com/docs/linux/show-post-49102.html