Возвращение логического значения из функции Bash - PullRequest
176 голосов
/ 25 марта 2011

Я хочу написать функцию bash, которая проверяет, имеет ли файл определенные свойства, и возвращает true или false.Затем я могу использовать его в своих сценариях в «если».Но что я должен вернуть?

function myfun(){ ... return 0; else return 1; fi;}

тогда я использую это так:

if myfun filename.txt; then ...

конечно, это не работает.Как это можно сделать?

Ответы [ 5 ]

284 голосов
/ 25 марта 2011

Используйте 0 для true и 1 для false.

Пример:

#!/bin/bash

isdirectory() {
  if [ -d "$1" ]
  then
    # 0 = true
    return 0 
  else
    # 1 = false
    return 1
  fi
}


if isdirectory $1; then echo "is directory"; else echo "nopes"; fi

Редактировать

Из комментария @ amichair это также возможно

isdirectory() {
  if [ -d "$1" ]
  then
    true
  else
    false
  fi
}


isdirectory() {
  [ -d "$1" ]
}
116 голосов
/ 08 мая 2017

Почему вы должны заботиться о том, что я говорю, несмотря на то, что есть ответ 250+ upvote

Дело не в 0 = true, а 1 = false. Это: ноль означает отсутствие отказа (успех) и ненулевое значение означает отказ (типа N) .

Хотя выбранный ответ технически "верен" , пожалуйста не вводите return 1** в свой код для ложь . У него будет несколько неприятных побочных эффектов.

  1. Опытные разработчики заметят вас как любителя (по причине ниже).
  2. Опытные разработчики этого не делают (по всем причинам, указанным ниже).
  3. Это подвержено ошибкам.
    • Даже опытные разработчики могут ошибочно принять 0 и 1 как false и true соответственно (по вышеуказанной причине).
  4. Требуются (или будут поощрять) посторонние и нелепые комментарии.
  5. На самом деле это менее полезно, чем неявные статусы возврата.

Узнай немного Баш

В руководстве bash написано (выделено мной)

return [n]

Заставить функцию оболочки прекратить выполнение и вернуть значение n вызывающей стороне. Если n не указано , возвращаемым значением будет состояние выхода последней команды, выполненной в функции.

Поэтому нам не нужно НИКОГДА использовать 0 и 1 для обозначения Истина и Ложь. Тот факт, что они делают это, по сути, является тривиальным знанием, полезным только для отладки кода, вопросов для интервью и для того, чтобы поразить умы новичков.

В руководстве по bash также написано

в противном случае статус возврата функции - это статус выхода последней выполненной команды

Руководство по bash также гласит

( $? ) Расширяется до состояния выхода последнего выполненного переднего плана конвейера .

Вау, подожди. Трубопровод? Давайте обратимся к руководству по bash еще раз.

Конвейер - это последовательность одной или нескольких команд , разделенных одним из управляющих операторов ‘|’ или ‘| &’.

Да. Они сказали, что 1 команда - это конвейер. Таким образом, все 3 из этих цитат говорят то же самое.

  • $? рассказывает, что произошло в последний раз.
  • пузырится.

Мой ответ

Итак, хотя @ Kambus продемонстрировал , что с такой простой функцией return вообще не требуется. Я думаю было нереально просто по сравнению с потребностями большинства людей, которые будут читать это.

Почему return?

Если функция возвращает статус завершения своей последней команды, зачем вообще использовать return? Потому что это приводит к прекращению выполнения функции.

Остановить выполнение при нескольких условиях

01  function i_should(){
02      uname="$(uname -a)"
03
04      [[ "$uname" =~ Darwin ]] && return
05
06      if [[ "$uname" =~ Ubuntu ]]; then
07          release="$(lsb_release -a)"
08          [[ "$release" =~ LTS ]]
09          return
10      fi
11
12      false
13  }
14
15  function do_it(){
16      echo "Hello, old friend."
17  }
18
19  if i_should; then
20    do_it
21  fi

Что у нас здесь есть ...

Строка 04 является явным [-ish] возвращаемым значением true, потому что RHS && выполняется только в том случае, если LHS был истинным

Строка 09 возвращает значение true или false, соответствующее статусу строки 08

Строка 13 возвращает false из-за строки 12

(Да, это может быть проигнорировано, но весь пример придуман).

Еще одна распространенная модель

# Instead of doing this...
some_command
if [[ $? -eq 1 ]]; then
    echo "some_command failed"
fi

# Do this...
some_command
status=$?
if ! $(exit $status); then
    echo "some_command failed"
fi

Обратите внимание, как установка переменной status отражает значение $?. (Конечно, вы знаете, что означает $?, но кто-то менее знающий, чем вы, придется когда-нибудь его Google. Если ваш код не занимается высокочастотной торговлей, покажите немного любви , установите переменную.) Но реальный вывод состоит в том, что «если не существует статус» или, наоборот, «если выходной статус» можно прочитать вслух и объяснить их значение. Однако, этот последний может быть слишком амбициозным, потому что, увидев слово exit, вы можете подумать, что он выходит из сценария, а в действительности он выходит из подоболочки $(...).


** яЕсли вы абсолютно настаиваете на использовании return 1 для false, я предлагаю вам хотя бы использовать return 255 вместо этого.Это заставит вашего будущего себя или любого другого разработчика, который должен поддерживать ваш код, задать вопрос "почему это 255?"Тогда они, по крайней мере, будут обращать внимание и имеют больше шансов избежать ошибки.

31 голосов
/ 28 марта 2011
myfun(){
    [ -d "$1" ]
}
if myfun "path"; then
    echo yes
fi
# or
myfun "path" && echo yes
13 голосов
/ 25 апреля 2013

Будьте внимательны при проверке каталога только с параметром -d!
, если переменная $ 1 пуста, проверка все равно будет успешной.Чтобы быть уверенным, проверьте также, что переменная не пуста.

#! /bin/bash

is_directory(){

    if [[ -d $1 ]] && [[ -n $1 ]] ; then
        return 0
    else
        return 1
    fi

}


#Test
if is_directory $1 ; then
    echo "Directory exist"
else
    echo "Directory does not exist!" 
fi
1 голос
/ 11 июня 2013

Может сработать, если переписать это function myfun(){ ... return 0; else return 1; fi;} как это function myfun(){ ... return; else false; fi;}. То есть, если false - последняя инструкция в функции, вы получаете ложный результат для всей функции, но return в любом случае прерывает функцию с истинным результатом. Я верю, что это правда, по крайней мере, для моего переводчика bash.

...