web-dev-qa-db-ja.com

シェルスクリプトで呼び出された関数から値を返す

シェルスクリプトで呼び出された関数から値を返したい。おそらく構文が足りません。グローバル変数を使ってみました。しかしそれもまたうまくいきません。コードは次のとおりです。

lockdir="somedir"
test() {
    retval=""

    if mkdir "$lockdir"
        then    # Directory did not exist, but it was created successfully
            echo >&2 "successfully acquired lock: $lockdir"
            retval="true"
        else
            echo >&2 "cannot acquire lock, giving up on $lockdir"
            retval="false"
    fi
    return retval
}


retval=test()
if [ "$retval" == "true" ]
    then
        echo "directory not created"
    else
        echo "directory already created"
fi
107
Mridul Vishal

Bash関数はあなたが望むように直接文字列を返すことはできません。 3つのことができます。

  1. 文字列をエコーする
  2. 終了ステータスを返します。文字列ではなく数値です。
  3. 変数を共有する

これは他のシェルにも当てはまります。

これらのオプションをそれぞれ実行する方法は次のとおりです。

1.エコー弦

lockdir="somedir"
testlock(){
    retval=""
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval="true"
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval="false"
    fi
    echo "$retval"
}

retval=$( testlock )
if [ "$retval" == "true" ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

2.終了ステータスを返す

lockdir="somedir"
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
    return "$retval"
}

testlock
retval=$?
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

シェア変数

lockdir="somedir"
retval=-1
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
}

testlock
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi
231
olibre

あなたは一生懸命働いています。スクリプト全体は次のようになります。

 mkdir $ lockdir 2>/dev/nullの場合エコーロックはロックを取得しました。それ以外はエコーを取得できませんでした

しかしそれでも多すぎる場合があります。私はそれをコーディングします:

 mkdir $ lockdir || 1番出口

しかし、表示されるエラーメッセージは少しわかりにくいです。

14
William Pursell

それが単なる真偽判定であるならば、成功のためにあなたの関数return 0を、そして失敗のためにreturn 1を持ってください。テストは次のようになります。

if function_name; then
  do something
else
  error condition
fi
10
glenn jackman

私は、succ/1が失敗(glenn jackman)の場合は0を返し、olibreの明確で説明的な答えはそれをすべて言っていると思います。結果がバイナリではなく、結果を「エコーアウト」するのではなく変数を設定したい場合のための一種の「コンボ」アプローチを言及するだけです(たとえば、関数が何かをエコーすると想定している場合うまくいかない)。それで何? (以下はBourne Shellです)

# Syntax _w (wrapReturn)
# arg1 : method to wrap
# arg2 : variable to set
_w(){
eval $1
read $2 <<EOF
$?
EOF
eval $2=\$$2
}

(ええ、例はやや愚かです、それはちょうど..例です)

getDay(){
  d=`date '+%d'`
  [ $d -gt 255 ] && echo "Oh no a return value is 0-255!" && BAIL=0 # this will of course never happen, it's just to clarify the nature of returns
  return $d
}

dayzToSalary(){
  daysLeft=0
  if [ $1 -lt 26 ]; then 
      daysLeft=`expr 25 - $1`
  else
     lastDayInMonth=`date -d "`date +%Y%m01` +1 month -1 day" +%d`
     rest=`expr $lastDayInMonth - 25`
     daysLeft=`expr 25 + $rest`
  fi
  echo "Mate, it's another $daysLeft days.."
}

# main
_w getDay DAY # call getDay, save the result in the DAY variable
dayzToSalary $DAY
1
Ola Aronsson