return和exit命令之间的差异
1. 概述
return和exit命令用于类似的目的 。一般来说,return的目的是退出Bash 函数,而exit的目的是退出Bash 脚本 。
在本教程中,我们将使用几个示例来讨论这两个命令之间的区别。
2. return命令
** return停止 Bash 函数的执行。**
如果我们为return提供一个整数参数,它会将该参数作为退出状态返回给函数调用者。否则,它将返回函数调用者之前执行的最后一个命令的退出状态。
2.1. 使用return退出 Bash 函数
让我们使用以下 Bash 脚本examine_return.sh检查return的行为:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
return $1
fi
ls /non_existing_file >& /dev/null
return
}
foo 5
echo “The return value of \”foo 5\” : $?”
foo
echo “The return value of \”foo\” : $?”
此脚本中的*foo()函数检查我们是否使用if [ ! –z “$1” ]*语句。
如果我们将参数传递给foo()函数,则条件表达式变为真。在这种情况下,该函数只是停止执行并使用return $1语句将作为参数传递给调用者的值返回。
如果我们不向foo()函数传递参数,则条件表达式[ ! –z “$1” ]变为假。在这种情况下,执行跳转到ls /non_existing_file >& /dev/null语句。如果文件不存在,ls命令返回*2 *。
然后我们退出foo()函数调用return而不带任何参数。事实上,显式调用return是多余的,因为它是函数中的最后一个命令。
最后,我们在脚本中调用了两次foo()函数。在第一次调用中,我们通过将参数5传递给它来调用它。在第二次调用中,我们在不传递任何参数的情况下调用它。我们使用echo命令和*$?* 在这两种情况下。
让我们运行脚本examine_return.sh并查看结果:
$ examine_return.sh
The return value of ”foo 5” : 5
The return value of ”foo” : 2
如我们所见,结果符合预期。第一个函数调用的退出状态是5,因为我们将5作为参数传递给函数。另一方面,第二个函数调用的退出状态为2,因为这是ls /non_existing_file >& /dev/null命令的退出状态,这是退出函数之前执行的最后一个命令。
2.2. 使用return退出 Bash 脚本
如果我们使用return退出脚本怎么办?让我们使用examine_return_from_script.sh 来尝试一下,它是我们看到的前一个版本的略微修改版本:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
return $1
fi
ls /non_existing_file >& /dev/null
return
}
foo 5
echo “The return value of \”foo 5\” : $?”
foo
echo “The return value of \”foo\” : $?”
return 0
这个修改后的脚本版本与之前的脚本相同,只是增加了一个——脚本末尾的最后一个*return语句。*让我们运行这个脚本:
$ examine_return_from_script.sh
The return value of "foo 5" : 5
The return value of "foo" : 2
examine_return_from_script.sh: line 20: return: can only ‘return’ from a function or sourced script
我们遇到了一个错误,所以我们不能使用return退出脚本。
但是,正如脚本的输出所示,我们可以使用source命令运行脚本:
$ source examine_return_from_script.sh
The return value of ”foo 5” : 5
The return value of ”foo” : 2
$ echo $?
0
从输出中可以明显看出,脚本的退出状态为0,这是return 0的结果。
3. exit命令
**我们使用exit从 Bash 脚本中退出。**我们在脚本中的什么地方调用它并不重要。例如,我们可以在 Bash 函数内部或外部调用exit 。
类似于return,它可能需要一个整数参数。在这种情况下,脚本退出时退出状态设置为整数参数。如果我们不向exit传递参数,它将退出,退出状态设置为exit之前执行的最后一个命令的退出状态。
3.1. 在 Bash 函数中使用exit
让我们使用以下脚本examine_exit.sh检查 Bash 函数中exit的行为:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
exit $1
fi
ls /non_existing_file >& /dev/null
exit
}
if [ ! –z “$1” ]
then
foo $1
else
foo
fi
echo “This line will not be printed”
此脚本中的foo()函数与examine_return.sh中的函数非常相似。我们只是用exit命令替换了return命令。我们还在脚本的末尾添加了一个echo命令,以证明脚本在exit后立即退出。
稍后,我们在脚本中调用*foo()函数。如果我们通过向脚本传递参数来运行脚本,我们通过向函数传递相同的参数来调用foo()函数。如果我们不带任何参数运行脚本,我们将调用不带任何参数的foo()*函数。
现在,让我们运行脚本:
$ examine_exit.sh 6
$ echo $?
6
$ examine_exit.sh
$ echo $?
2
在脚本的第一次执行中,它以退出状态6退出。在第二次执行中,不带任何参数,脚本以退出状态2 退出,这是退出前ls命令的退出状态。
由于我们在foo()函数调用中立即退出了脚本,因此两次运行中的echo命令都没有输出。
3.2. 在 Bash 函数外使用exit
我们还展示了我们可以在 Bash 函数外部使用exit来退出脚本。我们有以下脚本examine_exit_anywhere.sh:
#!/bin/bash
echo “This line will be printed”
exit 0
echo “But this line will not be printed”
foo()
{
if [ ! –z “$1” ]
then
exit $1
fi
ls /non_existing_file >& /dev/null
exit
}
if [ ! –z “$1” ]
then
foo $1
else
foo
fi
echo “This line will not be printed”
该脚本与我们之前使用的脚本examine_exit.sh非常相似。我们刚刚将两个echo命令添加到脚本的开头,并在它们之间添加了exit 0命令。 让我们运行脚本:
$ examine_exit_anywhere.sh
This line will be printed
$ echo $?
0
如我们所见,第一个echo被执行了。echo后的exit 0导致脚本退出,退出状态为 0。脚本其余部分中的命令未执行。
4. 使用trap命令和exit
exit和return的另一个区别与trap命令有关。通常,我们使用trap来处理信号,但是如果我们将 EXIT 指定为trap的信号, 则当脚本以exit退出时,将执行分配给trap的操作。
让我们用以下脚本examine_trap.sh来阐明这一点:
#!/bin/bash
trap “echo This line will be printed at exit” EXIT
foo()
{
echo “I am inside the foo function”
return 0
}
foo
echo “I am outside the foo function”
exit 0
脚本开头的trap只是调用echo命令。foo()函数仅打印一条消息并使用return返回。最后,在打印另一条消息后,我们使用exit退出脚本。
让我们运行脚本:
$ examine_trap.sh
I am inside the foo function
I am outside the foo function
This line will be printed at exit
正如我们所见,虽然我们在exit之前调用了return ,但trap中的消息是在exit之后打印的。因此,shell 在 EXIT 上为exit执行陷阱,但不为return执行陷阱。