shell 腳本編程學習(六) 函數

函數

和大多數編程語言一樣,shell 腳本也支持函數。在 shell 可以用下面的方式定義和使用函數:

#!/bin/bash

# 定義函數
sayHello () {
    echo "hello $1"    
}

# 調用函數並傳遞參數
sayHello jack

上面的例子將輸出“hello jack”。shell 中雖然也有函數的概念,但和 c、php、js 等編程語言中函數不太一樣,shell 腳本中的函數更像是注入在主 shell 腳本中的一段子腳本,調用函數就像是運行這段子腳本,但它不是在新的進程中運行,所以可以和主 shell 腳本共享變量和函數。函數也可以像 shell 腳本那樣通過 $0、$1 等變量獲取參數。還要注意 shell 函數的調用一定要在函數定義之後,解釋器是順序解析的,在函數定義之前調用函數將報錯。

另外,就像 shell 腳本通過 exit code 返回狀態碼那樣,函數也可以通過 return code 的方式返回一個狀態碼。但要注意狀態碼不是文本數據,無法輸出,想要返回文本數據可以在函數中 echo 文本數據,再通過反引號或 $() 的方式解析,例如:

#!/bin/bash

# 函數返回狀態碼
getCode() {
    return 0
}
code=`getCode`
echo $code
# 輸出爲空

# 函數返回文本值
getData () {
    echo "some text"    
}
data=`getData`
echo "data is $data"
# 輸出爲 data is some text

最後 shell 函數也支持嵌套和遞歸調用,讓我們可以實現一些複雜的算法邏輯,當然這樣會比較吃資源。

#!/bin/bash

# shell 遞歸實現斐波那契數列
fibo () {
    # 獲取參數,即想輸出數列的第幾個值
    index=$1

    # index 爲 1 或 2 時值爲 1
    # 用 -lt 選項進行數字小於比較,具體請參考 test 命令幫助
    if [ $index -lt 3 ]; then 
        echo 1
    else
        # index 大於等於 3 時數列值爲前兩項的和
        # 注意 shell 中變量都爲字符串類型,要藉助 expr 命令進行數字計算
        n1=`expr $index - 1`
        n2=`expr $index - 2`
        expr `fibo n2` + `fibo n1`  
    fi
}

# 調用函數求斐波那契數列第 10 項的值 
fibo 10

作用域

談到函數當然逃不開作用域。在 shell 腳本中默認所有的變量都在全局作用域下,也就是全局變量。想要只在函數中有效的局部變量可以用 local 來聲明。

#!/bin/bash

# 變量作用域
func () {
    # 變量 val1 默認在全局作用域下
    val1=123 
    # 用 local 聲明變量 val2 爲局部變量 
    local val2=456

    echo "val1 in func is $val1"
    echo "val2 in func is $val2"
}

func
echo "val1 outsite is $val1"
echo "val2 outsite is $val2"

# 運行結果
# val1 in func is 123
# val2 in func is 456
# val1 outside is 123
# val2 outside is

使用 getopts

getopts 是 shell 內建的一個命令,它可以用來檢查和獲取傳遞給命令的選項和參數。它的用法如下

#!/bin/bash

# getopts 獲取選項和參數
# 腳本 getopts.sh
# getopts 的語法爲 getopts opstring name
# opstring 中可以指定腳本接受哪些選項,如果選項必須提供參數就在後面加冒號
# 例如下面的 'xy:z:' 表示腳本接受 -x -y -z 選項且 -y -z 選項必須提供參數
# name 是一個 shell 變量用來保存選項
# getopts 還通過 $OPTIND 保存參數的索引,$OPTARG 保存參數的值
while getopts 'xy:z:' name; do
    echo "$name" $OPTIND $OPTARG
done

# shell
./getopts.sh -xy "one" -z "two"

# 運行結果
# x 1
# y 3 one
# z 5 two

由於函數也可以看作是一段腳本,所以 getopts 命令也可以用在函數中來判斷和獲取函數接受的選項和參數。

函數庫

如果我們有一些通用的函數或處理在很多地方都用的上,那麼最好將他們做成庫文件供其他腳本調用。類似 php 的 include,shell 腳本想要包含其他腳本或者說是庫文件也很簡單,用 . 操作符就行了,點後面跟腳本文件名就可以運行指定的腳本,它們不是另起進程而是在同一進程下運行,所以可以共享變量和函數定義,這樣就實現了函數庫的效果。

例如下面的代碼將腳本 lib.sh 包含到當前腳本中,注意 . 操作符後面要有一個空格。另外也可以通過 source 來包含庫文件,與 . 操作符效果相同。

#!/bin/bash
# 將指定的腳本文件包含到當前腳本
. /root/lib/lib.sh

# 用 source 命令可以達到相同的目的 
source /root/lib/lib.sh 

# 包含之後就可以使用 lib.sh 中定義的變量和函數了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章