Возврат значения из функции bash

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

Функция работает нормально, если число допустимо, но показывает синтаксическую ошибку, если ввести недопустимое число.

user2179293
источник

Ответы:

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 означает отсутствие ошибки).

choroba
источник
Я не понимаю В примере 24.7 в tldp.org/LDP/abs/html/complexfunct.html функция возвращает максимальное значение, а не код выхода. Хотя ваше предложение работает, но я не могу понять, почему оно работает
user2179293 15.09.13
1
поскольку ваш тест состоит в том, чтобы выяснить, является ли ввод действительным 10-значным целым числом или нет, то есть true или false, функция возвращает либо 0, либо 1. Пример работы choroba, потому что if valnum "$num"эквивалентен, if valnum "$num" = 0т. е. «если это правда». Основное эмпирическое правило в сценариях sh: 0 = истина / успех, ненулевое = ложь / ошибка.
Cas
2
Кстати, «Расширенное руководство по написанию сценариев» не очень хорошее руководство - во многих случаях оно ошибочно и поощряет некоторые плохие методы написания сценариев. FAQ по Bash на mywiki.wooledge.org/BashFAQ - гораздо лучший ресурс.
Cas
ваша функция не работает, потому что она отображает строку «Неверное число», и вы затем делаете числовое сравнение между этой строкой и числом 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 case:

valNum "$num"
case $? in 

Если вам потребуется использовать код состояния позже, сохраните его в другой переменной, прежде чем он $?будет перезаписан следующей командой.

valNum "$num"
valNum_status=$?

То, что вы написали, не сработало, потому что подстановка команд $(…)распространяется на выходные данные функции, которая в вашем коде является либо сообщением об ошибке, либо пустым, никогда 1.

Если вам нужно передать больше информации, чем позволяет код состояния, из функций оболочки, у вас есть две возможности:

  • Напечатайте некоторый текст в стандартный вывод и вызовите функцию в подстановке команд: $(valNum "$num")
  • Назначьте одну или несколько переменных внутри функции и прочитайте эти переменные позже.
Жиль "ТАК - перестань быть злым"
источник
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. При попытке ввода действительного каталога состояние равно нулю ( 0 ). Не так, как почти все другие языки.

Правило № 1 - Сделать ...

  • ИСТИНА == 0
  • ЛОЖЬ! = 0

Мы должны помнить, что мы тестируем коды ошибок в ifинструкции Bash . Я установил константы, или вы можете использовать shell trueили falseкоманды.

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.

Еще одна вещь, testкоманда. Это выглядит так:

[[ some-expression ]]; 

Большую часть времени. И например:

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

Ноль (0) соответствует действительности . Почему? Ну, на странице руководства сказано, что один аргумент является « истиной », когда он НЕ равен NULL.

Ссылки:

воля
источник