Поведение оператора return в функциях bash
У меня возникли проблемы с пониманием поведения return
встроенного в bash. Вот пример script.
#!/bin/bash
dostuff() {
date | while true; do
echo returning 0
return 0
echo really-notreached
done
echo notreached
return 3
}
dostuff
echo returncode: $?
Выход этого script:
returning 0
notreached
returncode: 3
Если, однако, date |
удаляется из строки 4, вывод будет таким, каким я ожидал:
returning 0
returncode: 0
Похоже, что оператор return
, использованный выше, действует так, как я думал, что оператор break
должен вести себя, но только тогда, когда цикл находится справа от трубы. Почему это так? Я не мог найти ничего, чтобы объяснить это поведение на странице bash man или в Интернете. script действует аналогично в bash 4.1.5 и тире 0.5.5.
Ответы
Ответ 1
В сценарии date | while ...
этот цикл while выполняется в подоболочке из-за наличия канала. Таким образом, оператор return прерывает цикл, и конец подоболочки заканчивается, оставляя вашу функцию продолженной.
Вам нужно будет восстановить код для удаления конвейера, чтобы не было создано никаких подоболочек:
dostuff() {
# redirect from a process substitution instead of a pipeline
while true; do
echo returning 0
return 0
echo really-notreached
done < <(date)
echo notreached
return 3
}
Ответ 2
Но return
должен прервать вызов функции, а не подоболочку. exit
предназначен для завершения (под) оболочки. Я думаю, это некоторые недокументированные ошибки/особенности.
echo|return
, введенный в командную строку, выдает ошибку, правильная - return
должна быть в функции.
f(){ echo|return; }
принимается в bash/тире, но return
не завершает вызов функции.
Если return
завершает подоболочку, он будет работать вне функции. Итак, вывод: return
завершает подоболочку в функции, что странно.
Ответ 3
Дело в том, что подоболочка - это отдельный процесс
На самом деле у него нет способа сказать родительской оболочке: "Я ухожу из-за возврата"
В статусе выхода нет такой вещи, которая является единственной вещью, получаемой родительской оболочкой.