Возвращаемое значение из вызываемой функции в оболочке script

Я хочу вернуть значение из функции, вызванной в оболочке script. Возможно, мне не хватает синтаксиса. Я попытался использовать глобальные переменные. Но это тоже не работает. Код:

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

Ответ 1

Функция Bash не может вернуть строку так, как вы хотите. Вы можете сделать три вещи:

  • Эхо строка
  • Возвращает статус выхода, который является числом, а не строкой
  • Поделитесь переменной

Это также верно для некоторых других оболочек.

Здесь, как сделать каждый из этих параметров:

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

3. Использовать переменную

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

Ответ 2

Вы слишком усердно работаете. Весь ваш сценарий должен быть:

if mkdir "$lockdir" 2> /dev/null; then 
  echo lock acquired
else
  echo could not acquire lock >&2
fi

но даже это, вероятно, слишком многословно. Я бы написал это:

mkdir "$lockdir" || exit 1

но полученное сообщение об ошибке немного неясно.

Ответ 3

Если это просто истинный/ложный тест, выполните свою функцию return 0 для успеха и return 1 для отказа. Тогда тест будет следующим:

if function_name; then
  do something
else
  error condition
fi

Ответ 4

Я думаю, что возвращение 0 для succ/1 для неудачи (glenn jackman) и olibre ясно и объяснительный ответ говорит все это; просто упомянуть своего рода "комбинированный" подход для случаев, когда результаты не являются бинарными, и вы предпочли бы установить переменную, а не "отгонять" результат (например, если ваша функция ТАКЖЕ, предположим, что она что-то повторяет, этот подход будет не работа). Что тогда? (ниже - оболочка Бурна)

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

как в (yep, пример несколько глупый, это просто пример)

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 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 another $daysLeft days.."
}

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