Повернення значення з функції 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

Функція працює нормально, якщо число є дійсним, але показує синтаксичну помилку, якщо вводити неправильне число.

Відповіді:


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 означає відсутність помилки).


Я не розумію. У прикладі 24.7 в tldp.org/LDP/abs/html/complexfunct.html функція повертає максимальне значення, а не код виходу. Хоча ваша пропозиція працює, але я не в змозі зрозуміти, чому це працює
user2179293

1
оскільки ваш тест полягає у з'ясуванні, чи є вхідним дійсним десятизначне ціле число чи ні, тобто істинним чи хибним, функція повертає або 0, або 1. приклад choroba працює, оскільки if valnum "$num"еквівалентний, if valnum "$num" = 0тобто "якщо це правда". Основне правило в сценаріях sh полягає в тому, що 0 = істина / успіх, не нуль = помилка / помилка.
cas

2
До речі, "Посібник з розширеного сценарію" не дуже хороший посібник - він помиляється в багатьох питаннях і заохочує погану практику сценаріїв. FAQ про Bash на mywiki.wooledge.org/BashFAQ - це набагато кращий ресурс.
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

Якщо вам потрібно розмежувати коди відмов, зателефонуйте безпосередньо до цієї функції. Відразу після повернення код відмови доступний в $?. Потім ви можете перевірити це із заявою:

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

Ми повинні пам’ятати, що ми перевіряємо коди помилок у Bash- ifоператорі. Я налаштовую константи, або ви можете використовувати оболонку 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) є істинним . Чому? Добре сторінка людини говорить, що один аргумент є " істинним ", коли він НЕ-НУЛЬНИЙ.

посилання:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.