如果我有 test.sh:
#!/usr/bin/env bash
echo "$@"
bash test.sh
结果是1
知道为什么结果是 1 吗?另外,为什么要发送到 env 而不是直接发送到 bash?
更新:抱歉,我遗漏了一些代码,现在有了这些代码,就有意义了。
#!/usr/bin/env bash
main() {
echo ${1:-1}
}
main "$@"
答案1
我无法在 Ubuntu 18.04.1 上重现此问题。
您应该echo "$@"
在脚本之外进行测试。它将显示1
您是否之前输入过set 1
,或者任何先前的位置参数命令的结果set
(包括在启动脚本中)。
请注意,作为( ) 文件bash test.sh
运行,任何行都将被忽略。要执行此操作,您需要:test.sh
source
.
#!
!#
bash -c test.sh
至于为什么env
指定,我不知道,除非它是作为占位符添加的:如果它包含一个或多个环境规范,它将产生效果。例如,以下内容将指定bash
使用自定义启动文件运行:
!#/usr/bin/env BASH_ENV=BashStart bash
...
Attie 的回答表明的另一个原因是,在 OSX 中bash
默认情况下不是在 中/bin/
,而是env
在 中/usr/bin/
,就像在 Linux 中一样,因此!#/usr/bin/env bash
允许在bash
将在 Linux 或 OSX 中运行的脚本中将其指定为 shell。
答案2
这 ”缺失代码”十分有意义。
#!/usr/bin/env bash
main() {
echo ${1:-1}
}
main "$@"
在这里,我们调用该main
函数并提供"${@}"
(即:我们所有的参数,保持分离)。
当${@}
扩展为无(即:脚本被调用时没有参数)时,main()
使用不参数,因此函数${1:-1}
内部main()
将产生特殊效果,如“参数替换“语义。
具体来说,如果声明了且非 NULL,或者未声明或为 NULL,${parameter:-default}
则将扩展为 的值。请注意 的行为与 略有不同。${parameter}
default
${parameter:-default}
${parameter-default}
${parameter-default}
和几乎等同。仅当参数已声明但为空时,${parameter:-default}
extra才有区别。:
因此${1:-1}
将扩展到给定的第一个参数,或者默认为1
:
$ ./script.sh
1
$ ./script.sh test
test
/usr/bin/env
在shebang中的使用使我们能够“用作bash
解释器“而不提供完整路径bash
...env
将搜索当前环境${PATH}
并使用第一个匹配的候选项。shebang 需要解释器的绝对路径,我们可以通过使用来绕过这个限制env
。
这在 Python 脚本中很常见,因为解释器可以位于许多位置 - 尽管通常/usr/bin/python
它支持以下内容虚拟环境也。
看 ”为什么人们在 Python 脚本的第一行写 #!/usr/bin/env python shebang?” 以进行更多讨论。