Поведение оператора return в функциях bash - PullRequest
18 голосов
/ 18 августа 2011

У меня проблемы с пониманием поведения встроенного в bash return. Вот пример сценария.

#!/bin/bash

dostuff() {
    date | while true; do
        echo returning 0
        return 0
        echo really-notreached
    done

    echo notreached
    return 3
}

dostuff
echo returncode: $?

Вывод этого скрипта:

returning 0
notreached
returncode: 3

Если, однако, date | удаляется из строки 4, вывод будет таким, как я ожидал:

returning 0
returncode: 0

Похоже, что оператор return, использованный выше, действует так, как я думал, оператор break должен вести себя, но только тогда, когда цикл находится с правой стороны канала. Почему это так? Я не смог найти ничего, что могло бы объяснить это поведение на странице руководства bash или в Интернете. Сценарий действует одинаково в bash 4.1.5 и dash 0.5.5.

Ответы [ 4 ]

21 голосов
/ 18 августа 2011

В сценарии date | while ... цикл while выполняется в подоболочке из-за наличия канала.Таким образом, оператор return прерывает цикл, и subshell заканчивается, оставляя вашу функцию для продолжения.

Вам нужно будет восстановить код, чтобы удалить конвейер, чтобы не создавались подоболочки:

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
}
1 голос
/ 30 мая 2018

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

Если вы exit внутри функции, общая программа закроется.

Вы не можете return в основной части скрипта bash, вы можете только return внутри скрипта функции или источника.


Например:

#!/usr/bin/env bash

function doSomething {
    echo "a"
    return
    echo "b"  # this will not execute because it is after 'return'
}

function doSomethingElse {
    echo "d"
    exit 0
    echo "e"  # this will not execute because the program has exited
}

doSomething
echo "c"
doSomethingElse
echo "f"  # this will not execute because the program exited in 'doSomethingElse'

Запуск приведенного выше кода приведет к выводу:

a
c
d
1 голос
/ 29 июля 2013

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

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

1 голос
/ 18 октября 2011

Но return должен завершать вызов функции, а не подоболочка.exit предназначен для завершения (суб) оболочки.Я думаю, это какая-то недокументированная ошибка / фича.

echo|return, введенный в командной строке, выдает ошибку, это правильно - return должно быть в функции.f(){ echo|return; } принимается в bash / dash, но return не завершает вызов функции.

Если return завершает подоболочку, она будет работать вне функции.Итак, вывод таков: return завершает подоболочку в функции , что странно.

...