Bash 脚本无法与 `sh` 一起使用

Bash 脚本无法与 `sh` 一起使用

我正在测试一个简单的脚本,我想知道为什么它从目录执行时运行良好:./test.sh但是当我尝试使用“sh”命令时sh test.sh它不起作用:

test.sh: 3: test.sh: [[: not found
test.sh: 7: test.sh: [[: not found

脚本:

#!/usr/bin/env bash

if [[ $1 = one ]]
        then
        printf "%b" "two\n" >&2
        exit 0
elif [[ $1 = two ]]
then
        printf "%b" "one\n" >&2
        exit 0
else
        printf "%b" "Specify argument: one/two\n"
        exit 1
fi

答案1

概括

sh是与 不同的程序bash

细节

问题在于 Bourne shell ( sh) 不是 Bourne Again shell ( bash)。也就是说,sh 无法理解该[[指令。事实上,它[也无法理解。[是一个实际的程序或指向 /bin/test(或 /usr/bin/[, /usr/bin/test)的链接。

$ which [
/bin/[
$ ls -lh /bin/[
-r-xr-xr-x  2 root  wheel    42K Feb 29 17:11 /bin/[

当您直接通过 执行脚本时./test.sh,您会将脚本作为第一行指定的程序的第一个参数来调用。在本例中:

#!/usr/bin/env bash

通常,这直接是解释器(/bin/bash,或任何其他脚本解释器),但在您的情况下,您使用 env 在修改后的环境中运行程序 - 但后续参数仍然是 bash。实际上,./test.shbash test.sh

由于shbash是不同的 shell,具有不同的语法解释,因此您会看到该错误。如果您运行bash test.sh,您应该会看到预期的结果。

更多信息

其他人在评论中指出,/bin/sh可以是链接或其他 shell。从历史上看,sh是旧 AT&T Unix 上的 Bourne shell,在我看来是规范的后裔。然而,这在 BSD 变体中有所不同,并且随着时间的推移,在其他基于 Unix 的系统和发行版中也出现了分歧。如果您真的对内部工作原理感兴趣(包括 /bin/sh 和 /bin/bash 如何成为同一个程序并表现完全不同),请阅读以下内容:

超级用户:bash 和 sh 有什么区别

维基百科:Bourne shell

答案2

如上所述:/bin/sh 通常(但并非总是)调用符合 POSIX 标准的 Bourne shell。Bash 不是 Bourne。

当以“sh”调用时(例如当 /bin/sh 符号链接或链接到 /bin/bash 时),或者当在调用环境中定义 $POSIXLY_CORRECT 时,当使用 --posix 调用选项调用时,或者当执行了“set -o posix”时,Bash 将尝试模拟 Bourne。这可以测试 Bourne shell 脚本/命令是否符合 POSIX 标准。

或者,使用已知的 POSIX 兼容 shell 调用脚本/测试命令。'dash' 很接近,Korn shell (ksh) IIRC 也提供了兼容 POSIX 的选项。

相关内容