Intereting Posts
Ошибка с командой make и sudo make install в терминале Какой из них выбрать для управления журналом, systemd-journald или rsyslog? Причина использования корневого пространства жесткого диска Почему эта строка включена в сообщение журнала «logcheck»? Пользовательские комбинации клавиш в dwm nc -l в фоновом закрытии немедленно закрывается (nc -l 1234 &) Рекурсивно найти и заменить содержимое одного файла, используя ключ из другого файла Вентилятор Ubuntu и Asus n552vw cpu всегда высок awk + print line, только если первое поле начинается с строки как Linux1 Как grep все строки, где начальная строка заканчивается шаблоном, а конечная строка заканчивается другим? усечение имен файлов печатать строки с уникальными указанными полями Трубы Bash vs ksh как создать пользовательский сеанс рабочего стола для x2go Как увеличить размер раздела Linux (EXT4) без потери данных, когда раздел подкачки находится именно после него?

Неявный возврат в функции bash?

Скажем, у меня есть функция bash, например:

gmx(){ echo "foo"; } 

будет ли эта функция неявно возвращать выходное значение команды echo , или необходимо использовать return?

 gmx(){ echo "foo"; return $? } 

Я предполагаю, что, как работает bash, состояние выхода последней команды функции bash – это то, что возвращается, но не на 100% уверен.

return выполняет явный возврат из функции оболочки или «точечного сценария» (исходного сценария). Если return не выполняется, неявный возврат выполняется в конце функции оболочки или точечного скрипта.

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

Вот как return работает во всех shellх POSIX.

Например,

 gmx () { echo 'foo' return "$?" } 

следовательно, эквивалентно

 gmx () { echo 'foo' return } 

который так же, как

 gmx () { echo 'foo' } 

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

Из bash(1) страницы bash(1) :

При выполнении состояние выхода функции является состоянием выхода последней команды, выполненной в теле.

Я просто добавлю несколько предостережений к уже предоставленным ответам:

  • Несмотря на то, что return имеет особое значение для оболочки, с синтаксической точки зрения это встроенная команда оболочки, и оператор return анализируется, как и любая другая простая команда. Итак, это означает, что, как и в аргументе любой другой команды, $? без кавычек будет подвержен split + glob

    Итак, вам нужно процитировать этот $? чтобы избежать этого:

     return "$?" 
  • return обычно не принимает никаких опций ( ksh93 принимает обычные --help , --man , --author … хотя). Единственный ожидаемый аргумент (необязательный) – это код возврата. Диапазон принятых кодов возврата варьируется от оболочки к оболочке, и правильно ли отражается любое значение за пределами 0..255 в $? также варьируется от оболочки к оболочке. См. Код завершения по умолчанию, когда процесс завершается? для деталей об этом.

    Большинство оболочек принимают отрицательные числа (в конце концов, аргумент, передаваемый системному вызову _exit() / exitgroup() является целым exitgroup() , поэтому со значениями, охватывающими по крайней мере от -2 31 до 2 31 -1, поэтому имеет смысл только то, что оболочки принимают тот же диапазон для его функций).

    Большинство оболочек используют waitpid() и co. API для извлечения этого состояния выхода, однако в этом случае он усекается до числа от 0 до 255 при хранении в $? , Даже несмотря на то, что для вызова функции не требуется waitpid() процесс и использовать waitpid() для получения его состояния завершения, поскольку все выполняется в одном и том же процессе, многие оболочки также имитируют поведение waitpid() при вызове функций. Что означает, что даже если вы вызываете return с отрицательным значением, $? будет содержать положительное число.

    Теперь среди тех оболочек, для которых return принимает отрицательные числа (ksh88, ksh93, bash, zsh, pdksh и производные, отличные от mksh, yash), есть несколько (pdksh и yash), которым нужно записать их как return -- -123 иначе что -123 принимается за три -1 , -2 , -3 неверных параметра.

    Как pdksh и его производные (например, OpenBSD sh или posh ) сохраняют отрицательное число в $? , это значит, что return "$?" потерпит неудачу, когда $? содержит отрицательное число (что могло бы произойти, когда последней командой запуска была функция, которая возвратила отрицательное число).

    Так что return -- "$?" было бы лучше в этих снарядах. Однако обратите внимание, что хотя синтаксис поддерживается большинством оболочек, он не является POSIX и на практике не поддерживается производными mksh и ash.

    Итак, чтобы подвести итог, с shellми на основе pdksh, вы можете использовать отрицательные числа в аргументах функций, но если вы это сделаете, return "$@" не будет работать. В других shellх сработает return "$@" , и вам следует избегать использования отрицательных чисел (или чисел вне 0..255) в качестве аргументов для return .

  • Во всех известных мне shellх вызов return изнутри подоболочки, выполняемой внутри функции, приведет к выходу подоболочки (с указанным состоянием выхода, если какая-либо или та из последней выполненной команды), но не вызовет возврата из функции (для меня неясно, дает ли вам POSIX такую ​​гарантию, некоторые утверждают, что exit следует использовать вместо промежуточных оболочек выхода внутри функций). Например

     f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?" 

    будет выводить:

     still inside f. Exit status: 3 f exit status: 0 

Да, неявное возвращаемое значение функции – это состояние выхода последней выполненной команды. Это также верно в любой точке любого сценария оболочки. В любой точке последовательности выполнения скрипта текущее состояние выхода является состоянием выхода последней выполненной команды. Четная команда выполняется как часть присвоения переменной: var=$(exit 34) . Разница с функциями заключается в том, что функция может изменить состояние выхода в конце выполнения функции.

Альтернативный способ изменить «текущий статус выхода» – запустить вспомогательную оболочку и выйти из нее с любым необходимым статусом выхода:

 $ $(exit 34) $ echo "$?" 34 

И да, расширение статуса выхода нужно заключать в кавычки:

 $ IFS='123' $ $(exit 34) $ echo $? 4 

А (exit 34) тоже работает.
Некоторые могут утверждать, что более надежная конструкция должна быть $(return 34) , и что выход должен «завершить» выполняемый скрипт. Но $(return 34) не работает ни с одной версией bash. Так что это не портативно.

Самый безопасный способ установить статус выхода – это использовать его так, как он был разработан для работы, определения и return из функции:

 exitstatus(){ return "${1:-"$?"}"; } 

Итак, в конце функции. это абсолютно равносильно тому, что либо ничего, либо return либо return "$?" , Конец функции не обязательно должен означать «последнюю строку кода функции».

 #!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf 'foo '; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf 'baz '; exitstatus 89 return else printf 'baz '; exitstatus 90 fi } 

Распечатает:

 $ ./script foo 78 baz 89 baz 90 

Единственное практическое использование для "$?" это либо напечатать его значение: echo "$?" или сохранить его в переменной (так как это эфемерное значение и изменяется с каждой выполненной командой): exitstatus=$? (не забудьте export EXITSTATUS="$?" переменную в кавычки в таких командах, как export EXITSTATUS="$?" .

В команде return допустимый диапазон значений обычно составляет от 0 до 255, но следует понимать, что значения 126 + n используются некоторыми shellми для сигнализации о специальном состоянии выхода, поэтому общая рекомендация – использовать 0-125.