returnвыполняет явный возврат из функции оболочки или «точечного сценария» (исходного сценария). Если returnне выполняется, неявный возврат выполняется в конце функции оболочки или точечного скрипта.
Если returnвыполняется без параметра, это эквивалентно возвращению статуса завершения последней выполненной команды.
Так returnработает во всех оболочках POSIX.
Например,
gmx (){
echo 'foo'return"$?"}
следовательно, эквивалентно
gmx (){
echo 'foo'return}
который так же, как
gmx (){
echo 'foo'}
В общем, это очень редко, что вам нужно использовать $?вообще. Это действительно необходимо только в том случае, если вам нужно сохранить его для будущего использования, например, если вам нужно несколько раз исследовать его значение (в этом случае вы назначаете его значение переменной и выполняете серию тестов для этой переменной).
Недостатком использования returnявляется то, что для функций, определенных как f() (...; cmd; return), это предотвращает оптимизацию, которую выполняют несколько оболочек cmdв том же процессе, что и подоболочка. Для многих оболочек это также означает, что состояние выхода функции не несет информацию, cmdкоторая была убита, когда она есть (большинство оболочек не могут получить эту информацию в любом случае).
Стефан Шазелас
1
Обратите внимание, что для pdksh и некоторых его производных (таких как OpenBSD shили posh) вам понадобится, return -- "$?"если есть вероятность, что последняя команда была функцией, возвращающей отрицательное число. mksh(также основанный на pdksh) запрещает функциям возвращать отрицательные значения.
Стефан Шазелас
спасибо, это помогает, наверное, я не понимаю, как return xфункционирует иначе, чем exit x... единственное, что я знаю, это то, return xчто не выйдет из текущего процесса.
Александр Миллс
@AlexanderMills Ну, это то, что я сказал: returnиспользуется для возврата из функции или точечного скрипта. exitделает что-то совершенно другое (завершает процесс).
Кусалананда
да, это имеет смысл, я думаю, что я начинаю лучше справляться с этим
Александр Миллс
7
Со bash(1)страницы руководства :
При выполнении состояние выхода функции является состоянием выхода последней команды, выполненной в теле.
правильно, и следствием может быть то, что оператор return является не чем иным, как статусом выхода?
Александр Миллс
Я думаю, returnчто это встроенная команда - хотя return 1она отличается от других exit 1и так далее
Александр Миллс
1
msgstr "return [n]: Заставляет функцию прекратить выполнение и вернуть значение, указанное в n, вызывающей стороне. Если n опущено, возвращается статус последней команды, выполненной в теле функции." (ibid) Таким образом, returnпринудительно устанавливает состояние выхода функции в конкретное значение, если оно указано.
Игнасио Васкес-Абрамс
1
@AlexandwrMills Да, returnи exitоба являются встроенными, за исключением того, что returnмогут использоваться только внутри функции. Вы не можете завершить сценарий с return. Состояние выхода - это значение, которое возвращает команда. returnэто команда, которая возвращает это значение. Так что «заявление о возврате - не более, чем статус выхода», просто не совсем точно. Один - это значение, другой - команда плюс значение.
Сергей Колодяжный
1
@AlexanderMills, returnвозвращает из функции, exitвыходит из всей оболочки. Это точно так же, как, скажем, в C с returnvs. exit(n)или returnпротив sys.exit()в Python.
ilkkachu
2
Я просто добавлю несколько предостережений к уже предоставленным ответам:
Несмотря на то, что она returnимеет особое значение для оболочки, с синтаксической точки зрения это встроенная команда оболочки, и оператор return анализируется, как и любая другая простая команда. Таким образом, это означает, что, как в аргументе любой другой команды, без $?кавычек, будет подвергаться split + glob
Поэтому вам нужно процитировать это, $?чтобы избежать этого:
return"$?"
returnкак правило , не принимает никаких опций ( ksh93«s принимает обычный --help, --man, --author... хотя). Единственный ожидаемый аргумент (необязательный) - это код возврата. Диапазон принятых кодов возврата варьируется от оболочки к оболочке, и то, правильно ли отражено любое значение вне 0..255, $?также зависит от оболочки к оболочке. См. Код завершения по умолчанию, когда процесс завершается? для деталей об этом.
Большинство оболочек принимают отрицательные числа ( в конце концов, аргумент передается _exit()/ exitgroup()системным вызовом является int, поэтому со значениями , охватывающими , по меньшей мере -2 31 до 2 31 -1, так что имеет смысл только в том , что раковины принимают один и тот же диапазон для своих функций) ,
Большинство оболочек используют waitpid()и. API для извлечения этого состояния выхода, однако в этом случае он усекается до числа от 0 до 255 при сохранении в $?. Даже несмотря на то, что для вызова функции не требуется порождать процесс и использовать его 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.
Итак, чтобы подвести итог, с оболочками на основе pdksh, вы можете использовать отрицательные числа в аргументах функций, но если вы это сделаете, return "$@"не будет работать. В других оболочках return "$@"будет работать, и вы должны избегать использования отрицательных чисел (или чисел за пределами 0..255) в качестве аргументов return.
Во всех известных мне оболочках вызов returnизнутри подоболочки, выполняемой внутри функции, приведет к выходу подоболочки (с указанным состоянием выхода, если какая-либо из команд последней команды выполнялась), но не вызовет возврата из функции ( мне неясно, дает ли вам POSIX такую гарантию, некоторые утверждают, что exitследует использовать вместо выходных субоболочек внутри функций). Например
f(){(return3)
echo "still inside f. Exit status: $?"}
f
echo "f exit status: $?"
Да, неявное возвращаемое значение функции - это состояние выхода последней выполненной команды. Это также верно в любой точке любого сценария оболочки. В любой точке последовательности выполнения скрипта текущее состояние выхода является состоянием выхода последней выполненной команды. Даже команда , выполняемая в рамках присваивание переменной: 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 "$?". Конец функции не обязательно должен означать «последнюю строку кода функции».
Единственное практическое применение для "$?"- это либо напечатать его значение: echo "$?"либо сохранить его в переменной (так как это эфемерное значение и изменяться при каждой выполненной команде): exitstatus=$?(не забывайте заключать переменную в кавычки, например export EXITSTATUS="$?".
В returnкоманде допустимый диапазон значений обычно составляет от 0 до 255, но следует понимать, что значения 126 + nиспользуются некоторыми оболочками для сигнализации о специальном состоянии выхода, поэтому общая рекомендация - использовать 0-125.
return
является то, что для функций, определенных какf() (...; cmd; return)
, это предотвращает оптимизацию, которую выполняют несколько оболочекcmd
в том же процессе, что и подоболочка. Для многих оболочек это также означает, что состояние выхода функции не несет информацию,cmd
которая была убита, когда она есть (большинство оболочек не могут получить эту информацию в любом случае).sh
илиposh
) вам понадобится,return -- "$?"
если есть вероятность, что последняя команда была функцией, возвращающей отрицательное число.mksh
(также основанный на pdksh) запрещает функциям возвращать отрицательные значения.return x
функционирует иначе, чемexit x
... единственное, что я знаю, это то,return x
что не выйдет из текущего процесса.return
используется для возврата из функции или точечного скрипта.exit
делает что-то совершенно другое (завершает процесс).Со
bash(1)
страницы руководства :источник
return
что это встроенная команда - хотяreturn 1
она отличается от другихexit 1
и так далееreturn
принудительно устанавливает состояние выхода функции в конкретное значение, если оно указано.return
иexit
оба являются встроенными, за исключением того, чтоreturn
могут использоваться только внутри функции. Вы не можете завершить сценарий сreturn
. Состояние выхода - это значение, которое возвращает команда.return
это команда, которая возвращает это значение. Так что «заявление о возврате - не более, чем статус выхода», просто не совсем точно. Один - это значение, другой - команда плюс значение.return
возвращает из функции,exit
выходит из всей оболочки. Это точно так же, как, скажем, в C сreturn
vs.exit(n)
илиreturn
противsys.exit()
в Python.Я просто добавлю несколько предостережений к уже предоставленным ответам:
Несмотря на то, что она
return
имеет особое значение для оболочки, с синтаксической точки зрения это встроенная команда оболочки, и оператор return анализируется, как и любая другая простая команда. Таким образом, это означает, что, как в аргументе любой другой команды, без$?
кавычек, будет подвергаться split + globПоэтому вам нужно процитировать это,
$?
чтобы избежать этого:return
как правило , не принимает никаких опций (ksh93
«s принимает обычный--help
,--man
,--author
... хотя). Единственный ожидаемый аргумент (необязательный) - это код возврата. Диапазон принятых кодов возврата варьируется от оболочки к оболочке, и то, правильно ли отражено любое значение вне 0..255,$?
также зависит от оболочки к оболочке. См. Код завершения по умолчанию, когда процесс завершается? для деталей об этом.Большинство оболочек принимают отрицательные числа ( в конце концов, аргумент передается
_exit()
/exitgroup()
системным вызовом являетсяint
, поэтому со значениями , охватывающими , по меньшей мере -2 31 до 2 31 -1, так что имеет смысл только в том , что раковины принимают один и тот же диапазон для своих функций) ,Большинство оболочек используют
waitpid()
и. API для извлечения этого состояния выхода, однако в этом случае он усекается до числа от 0 до 255 при сохранении в$?
. Даже несмотря на то, что для вызова функции не требуется порождать процесс и использовать его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.Итак, чтобы подвести итог, с оболочками на основе pdksh, вы можете использовать отрицательные числа в аргументах функций, но если вы это сделаете,
return "$@"
не будет работать. В других оболочкахreturn "$@"
будет работать, и вы должны избегать использования отрицательных чисел (или чисел за пределами 0..255) в качестве аргументовreturn
.Во всех известных мне оболочках вызов
return
изнутри подоболочки, выполняемой внутри функции, приведет к выходу подоболочки (с указанным состоянием выхода, если какая-либо из команд последней команды выполнялась), но не вызовет возврата из функции ( мне неясно, дает ли вам POSIX такую гарантию, некоторые утверждают, чтоexit
следует использовать вместо выходных субоболочек внутри функций). Напримербудет выводить:
источник
Да, неявное возвращаемое значение функции - это состояние выхода последней выполненной команды. Это также верно в любой точке любого сценария оболочки. В любой точке последовательности выполнения скрипта текущее состояние выхода является состоянием выхода последней выполненной команды. Даже команда , выполняемая в рамках присваивание переменной:
var=$(exit 34)
. Разница с функциями заключается в том, что функция может изменить состояние выхода в конце выполнения функции.Альтернативный способ изменить «текущий статус выхода» - запустить вспомогательную оболочку и выйти из нее с любым необходимым статусом выхода:
И да, расширение статуса выхода нужно заключать в кавычки:
А
(exit 34)
также работа.Некоторые могут возразить, что более надежная конструкция должна быть
$(return 34)
и что выход должен «выйти» из выполняемого сценария. Но$(return 34)
не работает ни с одной версией bash. Так что это не портативно.Самый безопасный способ установить статус выхода - использовать его так, как он был разработан для работы, определения и
return
использования функции:Итак, в конце функции. это абсолютно равносильно тому, чтобы иметь ничего или
return
илиreturn "$?"
. Конец функции не обязательно должен означать «последнюю строку кода функции».Распечатает:
Единственное практическое применение для
"$?"
- это либо напечатать его значение:echo "$?"
либо сохранить его в переменной (так как это эфемерное значение и изменяться при каждой выполненной команде):exitstatus=$?
(не забывайте заключать переменную в кавычки, напримерexport EXITSTATUS="$?"
.В
return
команде допустимый диапазон значений обычно составляет от 0 до 255, но следует понимать, что значения126 + n
используются некоторыми оболочками для сигнализации о специальном состоянии выхода, поэтому общая рекомендация - использовать 0-125.источник