2015-04-03 95 views
1

這是我的代碼摘要。我使用func"true"中的return_val之間的比較結果來確定終止條件。但是回聲根本不起作用。如何在bash腳本中測試時使用函數返回值

#!/bin/bash 

func(){ 
    a=$1 
    b=$2 
    echo $a 
    echo $b 
    if ((a > b)) 
    then 
     return_val="true" 
    else 
     return_val="false" 
    fi 
} 

c=1 
d=4 
while [[ $(func $c $d) && ("$return_val"!="true") ]] 
do 
    ((c++)) 
done 

回答

1

既然你想看到您echo命令的輸出,需要將標準輸出輸出回報(退出)代碼分開:

#!/bin/bash 

func(){ 
    local a=$1 b=$2 
    echo "$a" # stdout output 
    echo "$b" 
    if ((a > b)) # see below for how this could be simplified. 
    then 
     return 0 # set exit code 
    else 
     return 1 
    fi 
} 

c=1 d=4 
while ! func $c $d 
do 
    ((c++)) 
done 

這樣的話,你可以自由地使用該函數直接(前綴!否定測試的結果),而沒有命令替換,並讓其返回(退出)的代碼驅動的while循環條件結果(的退出代碼意思是成功,其他意思失敗)。

僅使用! func $c $d作爲條件,func的標準輸出簡單地按原樣打印。


附錄Billy Wayne McCann's answer指出,沒有嚴格的需要使用明確的return語句設置退出代碼(但有沒有必要使用test[1])。

((a > b))可以通過自身使用作爲函數的最後一條語句,設置退出代碼隱含

如果沒有明確的return聲明,它是一個功能的最後命令,設置其退出代碼(在沒有exit聲明的情況下,類似地適用腳本)。

((...))設置退出代碼以1,如果...計算結果爲0,並1否則(任意非負的結果)。如果表達式爲真,那麼布爾表達式(例如a > b)會導致1,否則返回0。因此,((a > b))本身做同樣的事隱,上述if聲明確實明確

func(){ 
    local a=$1 b=$2 
    echo "$a" # stdout output 
    echo "$b" 
    ((a > b)) # exit code implicitly set to 0, if test *succeeds*, 1 otherwise 
} 

[1]使用test[ ... ]是POSIX兼容的方法來評估的條件。除非你的代碼必須是符合POSIX標準,bash的[[ ... ]]((...))(用於算術布爾測試)是更好的選擇 - 看https://stackoverflow.com/a/29320710/45375

+0

對不起,回聲用於調試。我瞭解到,我們應該返回退出狀態而不是價值。 – 2015-04-03 03:43:24

+0

@CodingTheLife:這就是這個解決方案的功能:函數的_exit code_決定何時退出循環。因此,無論輸出形成條件的命令如何產生都會通過。如果你不需要輸出,使用'>/dev/null'來抑制stdout,'2>/dev/null'來抑制stderr,'>/dev/null'來抑制兩者。由於你的問題表明「回聲不起作用」 - 你認爲這個解決方案確實「使它們工作」是什麼意思? 「 – mklement0 2015-04-03 03:49:05

1

我寧願讓函數返回一個值。

#!/bin/bash 

func(){ 
    a=$1 
    b=$2 
    echo $a 
    echo $b 
    if ((a > b)) 
    then 
     return 0 # 0 means success 
    else 
     return 1 # non-zer0 means failure 
    fi 
} 

c=1 
d=4 
until (func $c $d) #While ! success, do something.. 
do 
    ((c++)) 
done 

注:圍繞func $c $d的括號僅用於提高可讀性。不需要真的。

+2

@anishane:使用冗餘括號會產生冗餘子shell,因爲這是括號在bash中所做的。無論如何,恕我直言,'func $ c $ d;做'是完全可讀的(至少,一旦你習慣了bash)。 – rici 2015-04-03 03:42:46

1

強制的0或1的回報是不是這樣做的正確方法。您想要返回測試的真正退出狀態,而不是強制退回狀態。 if ... then區塊確實不需要。

函數自動返回它們的退出狀態。該函數的退出狀態是最終聲明的狀態。因此,您可以將test作爲func的最終聲明。

#!/usr/bin/env bash 

func(){ 
    local a=$1 
    local b=$2 
    test $a -lt $b #use exit status directly 
} 

c=1 
d=4 

while func $c $d #while c is less than d 
do 
    ((c++)) 
done 
+1

」不是這樣做的正確方法。「是誇張的 - 接受的答案是_proper_,但是_needlessly verbose_。 '((a> b))'本身將作爲最後一個語句 - 不需要使用靈活性較低且功能較弱的'test'內建代替。 – mklement0 2015-04-03 21:59:35

+0

爲了闡明我以前的評論:你簡單地讓測試的結果決定函數的退出代碼_implicitly_是一個很好的建議。儘管接受答案中的if語句實際上是_redundant_,但是它不會_mask_'((...))'表達式的退出代碼,因爲'((...))'本身只設置退出代碼0或1.(即使有__要屏蔽,只有當你隨後測試了一個特定的退出代碼集時纔會發生,這很少發生;在手邊的情況下,'while'只關心0與非0)。 – mklement0 2015-04-04 14:01:36

+0

' a'和'b'也是不必要的冗長; 'func(){test「$ 1」-lt「$ 2」;因爲你沒有修改參數,所以''會工作一致。 – chepner 2015-04-04 14:06:20