Shell中處理方法返回值問題

img

同步發表:http://blog.hacktons.cn/2017/12/13/shell-func-return/linux

背景

經過shell編程,寫一些工具批處理的時候,常常須要自定義函數。更復雜點的狀況下,可能有須要返回一個值。
因爲在shell的世界中,並不像其餘編程語言,它不支持咱們所熟悉的方法返回。本文一塊兒總結一下如何優雅的解決返回值問題?git

測試程序

咱們通常經過$?來獲取上一個語句的輸出。看一下下面得測試語句:github

新建testReturn腳本shell

returnString(){
    return $1
}

returnString $1
result=$?
echo "result=$result"

如今咱們有一個testReturn的腳本,裏面有一個returnString的方法,咱們但願它可以直接返回咱們輸入的參數。
當咱們分別以hello,500,12做爲輸入參數時,他的執行和輸出狀況是同樣的麼?編程

./testReturn hello
./testReturn 500
./testReturn 12

在心中試着猜一下可能的狀況,如今咱們來揭曉答案:bash

程序輸出狀況

在執行hello的時候,並無輸出hello,而是報了一個return只接受數字類型的錯誤編程語言

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
./testReturn: line 23: return: hello: numeric argument required
result=255

在執行500的時候,頁沒有輸出500,而是輸出了244函數

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=244

執行12的時候,終於正確了,返回12工具

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

異常分析

如今咱們分析一下returnString這個方法,爲何會有這麼多種輸出狀況呢?
首先他的寫法顯然是不嚴謹的,但也不是徹底錯誤,好比輸入12他就正確返回了。測試

return自己是shell裏面的buildin函數,筆者總結了下,他有如下幾個特徵:

  • return能夠返回數字狀態,經常用於返回0,1,標識一個函數執行後是否成功
  • 注意return不能夠返回非數字類型
  • 同時數字類型也有可能發生溢出現象

全局變量

若是咱們就是要返回一個字符串,怎麼辦呢?能夠經過定義全局變量來進行賦值,相似於靜態變量/成員變量的寫法,咱們讓他的做用域穿透整個上下文。

result=""
returnString(){
    result=$1
}

returnString $1
echo "result=$result"

再看一下輸出,獲得了咱們須要的結果:

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

可是這樣寫,會污染全局變量,而且result這個變量很容易在內部和外部都被修改,致使內部修改失效。

eval

除了return,還有其餘一些buildin的關鍵字,好比evallocal
默認在當前腳本定義的變量都是全局變量,在方法中則能夠經過local來定義局部變量,這樣能夠避免全局變量污染.
同時結合eval賦值語句,來實現變量的修改

returnString(){
    local __result=$2
    eval $__result=$1
}

returnString $1 result
echo "result=$result"

一樣咱們也獲得了但願的結果

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

echo

最後在介紹一種方法,經過echo輸出,結合command substitution
這個command substitution也沒有找到比較合適的翻譯,姑且按字面意思翻譯命令替換

若是你的方法內部只有一處echo輸出,那麼也能夠利用她來進行值得返回,不過這個就有點侷限性,必定要確保方法內只有一次輸出,不然就會出現賦值內容過多。

returnString(){
    local __result=$1
    echo $__result
}
# 或者 result=`returnString $1`
result=$(returnString $1)
echo "result=$result"

一樣能夠獲得預期結果

aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

越界問題

如今咱們已經有幾種辦法能夠返回字符串了,那麼return返回數字有時候正確,有時候又不正確是爲何呢?

咱們知道return本來就是用於返回執行狀態的,好比0,1.那麼咱們在返回500的時候,其實是數據溢出了。

根據測試,咱們推斷shell的內置return承接返回值用的是一個字節的大小,也就是8位,最多能夠輸出無符號0-255的整形,範圍以外的數據所有溢出顯示。所以在使用return的時候,務必留意數值大小。

小結

經過shell命令能夠很方便的寫出一些小腳本,可是若是遇到邏輯複雜,建議經過其餘更合適的預覽來實現,好比Python,Golang之類。

相關文章
相關標籤/搜索