在返回命令1

时间:2018-07-25 19:48:24

标签: bash

我知道标题有点奇怪,但我不确定如何更好地用词。

我正在使用$(return &> /dev/null)来检测文件是否是源文件。

我知道这种方法不是100%可靠的,但是到目前为止,它对我没有问题。我已经想出了解决该问题的方法,但是我不知道为什么会发生这种情况。

编辑:这是用于公司内部的项目,并不旨在与POSIX兼容或可移植到其他外壳。

我已经在三种不同的系统上进行了尝试,并且得到了相同的结果:

Redhat 6.9; $BASH_VERSION=4.1.2(1)-release
Mint 18.2; $BASH_VERSION=4.3.48(1)-release
Arch; $BASE_VERSION=4.4.23(1)-release

如果$?$(return &> /dev/null)为1(假),则返回码相反。

$ hr | cat test_0source - test_0source.sh; hr; ./test_0source
#!/bin/bash
# test_0source

false
test_0source.sh

false
source test_0source.sh

true
test_0source.sh

true
source test_0source.sh
========================================
#!/bin/bash
# test_0source.sh

# shellcheck disable=SC2091
$(return &> /dev/null)
echo "$?"
========================================
1
1
1
0

我希望能见到

1
0
1
0

我的解决方法是在true检查之前添加return。虽然这给了我正确的结果,但添加false而不是true会使return的检查始终返回1。

我意识到我在这里缺少一些基本的知识,但是我没有看到。为什么这样做呢?

编辑:我的$值不正确?在上面的最初解释中。

更新: 首先,由于@ ondre-k,使用$(return 0 &> /dev/null)可解决问题。

Ondre还指出,将BASH_SOURCE与$ 0进行比较是一种更惯用的方法:

$ hr | cat test_0bs - test_0bs.sh; hr; test_0bs | less
#!/bin/bash
# test_0bs

false
test_0bs.sh
hr

false
source test_0bs.sh
hr

true
test_0bs.sh
hr

true
source test_0bs.sh
========================================
#!/bin/bash
# test_0bs.sh

if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
  echo "We are not being sourced."
else
  echo "We are being sourced."
fi
========================================
We are not being sourced.
========================================
We are being sourced.
========================================
We are not being sourced.
========================================
We are being sourced.

我怀疑这周围可能有一个或两个极端的情况,但在我看来,这些情况将变得无关紧要。

1 个答案:

答案 0 :(得分:1)

您正在做的事情基本上是在“滥用”以下事实:返回只能从函数或源脚本中发生,并假设在可能返回(我们已获得源)和{{1}的情况下返回0如果不是,则在抑制错误输出的同时。您也可以在子shell中执行此操作。奇怪的是,使用1放置bash还是可以的,但是不会从源脚本中返回并继续运行。到目前为止,上帝。

问题是,“ {裸体”(未指定显式值)return,就像return传播最后看到的返回代码(紧接其后的命令的返回代码)。

换句话说,exitfalse; return是同一件事。您也可以通过将return 1替换truefalse来尝试一下,看看会发生什么。您在测试中寻找到(exit 255)的{​​{1}}不是错误,而是测试过程中的“错误:您现在不能说1”,而只是一个普通的{{1 }}已从其前面的命令(return)返回了最后一个。如果您放弃了return重定向,这种区别也将变得显而易见。

TL; DR可以使此构造按预期工作,将其更改为return


我希望我不会错过一些极端的情况,但是通过比较执行脚本的名称和源文件,这可以作为bash的替代方法。如果没有源文件,则false的计算结果为stderr,如果有文件,则计算结果为return 0。或将[[ "${BASH_SOURCE}" = ${0} ]]替换为0,以获得与上述1情况相同的值含义。