bash関数から値を返す


10

数値が有効な10桁の数値である場合に1を返す関数があります。

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

それは以下によって呼び出されています:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

数値が有効であれば関数は正常に機能しますが、無効な数値を入力すると構文エラーが表示されます。

回答:


14

@chorobaの答えは正しいですが、この例はより明確かもしれません:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

この例は少し長くなっていますが(設定して$valNumResultからその値をクエリする)、何が起こるかをより明確に説明していvalNum()ます。つまり、値を返し、その値をクエリしてテストできます。

PS自分でお願いし、のためにゼロ以外の値0を返しtrueますfalse。これにより、戻り値を使用して、失敗した場合に「失敗した理由」を示すことができます。


8

bashの関数は終了コードのみを返すことができます。逆に、コマンド置換は、コマンドまたは関数の標準出力を取得するために使用されます。したがって、返されたフラグを確認するために、置換は必要ありません。

if valNum "$num" ; then
    # ...
fi

ただし、機能するためには、数値が有効な場合は0を返し、有効でない場合は1を返す必要があります(出口コード0はエラーがないことを意味します)。


わかりません。tldp.org/LDP/abs/html/complexfunct.htmlの例24.7 では、関数は終了コードではなく最大値を返しています。あなたの提案は機能していますが、なぜ機能しているのか理解できません
user2179293

1
あなたのテストは、入力、すなわち、真または偽の有効な10桁の整数であるかどうかを調べることであるため、関数が返す0または1 chorobaの例があるために働くif valnum "$num"と等価であるif valnum "$num" = 0「それが真の場合」、すなわち。shスクリプトの基本的な経験則は、0 = true /成功、0以外= false /エラーです。
cas

2
ところで、その「高度なBashスクリプトガイド」はあまり良いガイドではありません。多くの点で間違っており、不適切なスクリプトの実践を奨励しています。mywiki.wooledge.org/BashFAQのBash FAQ は、はるかに優れたリソースです。
cas


文字列 "Invalid Number"をエコーするため、関数は失敗します。次に、その文字列と数値1の間の数値比較をif [[ $(valNum $num) -eq 1 ]]
cas

5

シェル関数から任意の結果を返すことはできません。0から255までの整数であるステータスコードのみを返すことができます(より大きい値をに渡すことはできますがreturn、256を法として切り捨てられます)。成功を示すには値が0であり、失敗を示すには別の値でなければなりません。高い値には特別な意味があるため、慣例では1〜125のエラーコードに固執する必要があります(126と127の不良外部コマンド、高い値の信号によって強制終了されます)。

ここでは「はい」または「いいえ」の結果が返されるため、ステータスコードが適切です。以来flag、成功または失敗を示すように見える、あなたは失敗(あなたが書いたものの反対側)のための成功のための0と1の従来の値を使用する必要があります。その後、ifステートメントで関数を直接使用できます。

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

失敗コードを区別する必要がある場合は、関数を直接呼び出します。復帰した直後に、障害コードがで利用可能です$?。次に、caseステートメントで確認できます。

valNum "$num"
case $? in 

後でステータスコードを使用する必要がある場合は$?、次のコマンドで上書きされる前に、ステータスコードを別の変数に保存してください。

valNum "$num"
valNum_status=$?

コマンドの置換$(…)が関数の出力に拡張されるため、記述した内容は機能しませんでした1。コードでは、エラーメッセージまたは空のどちらかであり、決してありません。

ステータスコードがシェル関数から許可するよりも多くの情報を渡す必要がある場合、2つの可能性があります。

  • 標準出力にテキストを出力し、コマンド置換で関数を呼び出します。 $(valNum "$num")
  • 関数内の1つ以上の変数に割り当て、それらの変数を後で読み取ります。

2

私自身、この分野で相反する結果がありました。これが私の経験的実験の結果です。まず、bashまたは* nixコマンドに関するいくつかの「理論」:

  • 成功== 0 ...つまり エラーステータスコードなし)
  • FAIL!= 0 ......いくつかのステータスコード

例:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

出力:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

示されているように、lsコマンドはステータスコード= 2を返します。有効なディレクトリを試行すると、ステータスはzero(0)になります。他のほとんどすべての言語と同じではありません。

ルール#1-作成 ...

  • 真== 0
  • FALSE!= 0

Bash ステートメントでエラーコードをテストしていることを忘れないでifください。定数を設定したり、シェルtruefalseコマンドを使用したりできます。

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

そして出力:

Invalid Number
Not lucky.

しかし、彼の答えは正しいので、「賛成票」@Gilles を与えることをお勧めします。私はePaperの単純化した側面を取り除きたかっただけです。

もう1つ、testコマンドです。これは次のようになります。

[[ some-expression ]]; 

ほとんどの時間。そして例えば:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

Zero(0)はtrueです。どうして?まあ、manページでは、NOT-NULLの場合、単一の引数は「true」であると述べています。

参照:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.