Поведение оператора 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

Дело в том, что подоболочка - это отдельный процесс На самом деле у него нет способа сказать родительской оболочке: "Я ухожу из-за возврата"

В статусе выхода нет такой вещи, которая является единственной вещью, получаемой родительской оболочкой.