bash函数中return语句的行为

时间:2011-08-18 15:09:38

标签: bash function return

我无法理解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

但是,如果从第4行删除date |,则输出符合我的预期:

returning 0
returncode: 0

上面使用的return语句似乎就像我认为break语句应该表现的方式一样,但只有当循环位于管道的右侧时。为什么会这样?我无法在bash手册页或在线中找到任何解释此行为的内容。该脚本在bash 4.1.5和破折号0.5.5中的行为方式相同。

5 个答案:

答案 0 :(得分:21)

date | while ...场景中,由于管道的存在,while循环在子shell中执行。因此,return语句打破了循环, subshel​​l 结束,让你的函数继续运行。

您必须重新构建代码才能删除管道,以便不会创建子shell:

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 :(得分:1)

但是return应该终止函数调用,而不是子shell。 exit旨在终止(子)shell。我想,这是一些无证的bug /功能。

  • echo|return输入命令行会出错,这是正确的 - return应该在函数中。
  • f(){ echo|return; }在bash / dash中被接受,但return不会终止函数调用。

    如果return终止子shell,它将在函数外部工作。因此,结论是: return终止函数中的子shell ,这很奇怪。

  • 答案 2 :(得分:1)

    事情是:子shell是一个单独的过程 它实际上没有办法对父shell说:“我因为返回而退出”

    在退出状态中没有这样的东西,这是父shell获得的唯一东西。

    答案 3 :(得分:1)

    如果函数内部return,该函数将停止执行,但整个程序不会退出。

    如果您在函数内部exit,则整个程序将退出。

    您不能在bash脚本的主体中return,只能在函数或源脚本中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
    

    答案 4 :(得分:0)

    添加答案以解决bash的这一有趣功能。 。 。

    • 返回if(或带有if / while / ...等表达式的任何控制命令)

    • 如果使用简单和不太简单的表达式返回内部

    subshel​​l解释很好。控件返回到当前子外壳程序之外。这可能是bash函数。或者它可能是任何嵌套控制命令中带有导致子壳被调用的表达式。

    1. 用于非常简单的表达式,例如“ true”或“ 1 == 1”,不会调用任何子shell。因此return表现为〜normal / expected〜。

    2. 用于不太简单的表达式,例如扩展变量并与之比较,然后返回的行为就像中断;

    简单(无子shell)示例:

    $ rtest () { if true; then echo one; return 2; echo two; fi; echo not simple; return 7; }
    $ rtest
    one
    $ echo $?
    2
    
    $ rtest () { if [[ 1 == 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
    $ rtest
    one
    $ echo $?
    2
    
    $ rtest () { if [[ 1 =~ 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
    $ rtest
    one
    $ echo $?
    2
    
    $ rtest () { if $DO ; then echo one; return 2; echo two; else echo three; return 3; fi; echo not simple; return 7; }
    $ rtest
    one
    $ echo $?
    2
    
    $ rtest () { if [[ $DO ]]; then echo one; return 2; echo two; else echo three; return 3; fi; echo not simple; return 7; }
    $ rtest
    three
    $ echo $?
    3
    
    $ rtest () { if [[ $DO == 1 ]] ; then echo one; return 2; echo two; else echo three; return 3; echo four; fi; echo not simple; return 7; }
    $ rtest; echo $?
    one
    2
    $ DO=1; rtest; echo $?
    one
    2
    $ DO=0; rtest; echo $?
    three
    3
    

    表达并不简单,并假定调用了subshel​​l,返回行为就像break;

    不简单(子外壳)示例。 。 = [[[]]内部:

    $ rtest () { if [[ $DO =~ 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
    $ rtest
    not simple
    $ echo $?
    7