在Bash中,我希望能够同时获取脚本并执行该文件。什么是Bash相当于Python的if __name__ == '__main__'
?
我没有在Stackoverflow上找到关于这个主题的现成问题/解决方案(我怀疑我问的方式与现有的问题/答案不符,但这是我能想到的最明显的方式因为我的Python经验来表达这个问题。)
P.S。关于possible duplicate question(如果我有更多时间,我会写一个较短的回复):
linked to question询问“如何检测脚本是否被源”但是这个问题询问“如何创建一个既可以源代码又可以作为脚本运行的bash脚本?”。这个问题的答案可能会使用前一个问题的某些方面,但还有其他要求/问题如下:
答案 0 :(得分:20)
解决方案:
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
我添加了这个答案,因为我想要一个用模式编写的答案来模仿Python的if __name__ == '__main__'
,但是在Bash中。
关于BASH_SOURCE
vs $_
的使用情况。我使用BASH_SOURCE
,因为它似乎比$_
(link1,link2)更强大。
以下是我使用两个Bash脚本测试/验证的示例。
带有xyz()
功能的script1.sh:
#!/bin/bash
xyz() {
echo "Entering script1's xyz()"
}
main() {
xyz
echo "Entering script1's main()"
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
尝试调用函数xyz()
的script2.sh:
#!/bin/bash
source script1.sh
xyz
答案 1 :(得分:7)
没有。我通常用这个:
#!/bin/bash
main()
{
# validate parameters
echo "In main: $@"
# your code here
}
main "$@"
如果您想知道此脚本是否为source
,请将main
电话打包到
if [[ "$_" != "$0" ]]; then
echo "Script is being sourced, not calling main()"
else
echo "Script is a subshell, calling main()"
main "$@"
fi
答案 2 :(得分:4)
FUNCNAME
FUNCNAME[0]
(Bash 4.3 +)#!/bin/bash
main(){
echo "hello"
}
if [[ ${FUNCNAME[0]} == "main" ]]; then
main
fi
示例运行:
$ bash funcname_test.sh
hello
$ source funcname_test.sh
$ main
hello
我不确定我是如何偶然发现的。 man bash没有很好地描述其功能,但实际上它的实际作用是:
${FUNCNAME[0]}
为main
${FUNCNAME[0]}
为source
${FUNCNAME[0]}
是函数的名称FUNCNAME[1]
(Bash 4.2)在Bash 4.2中,FUNCNAME
仅在函数中可用,其中FUNCNAME[0]
是函数的名称,FUNCNAME[1]
是调用者的名称。因此,对于顶级函数,FUNCNAME[1]
将在已执行的脚本中为main
,或在源脚本中为source
。
这个例子应该像上面的例子一样工作。
#!/bin/bash
get_funcname_1(){
echo "${FUNCNAME[1]}"
}
main(){
echo hello
}
if [[ $(get_funcname_1) == main ]]; then
main
fi
答案 3 :(得分:2)
对于惯用的Bash方式,您可以像这样使用return
:
main(){
echo hello
}
# End sourced section
return 2> /dev/null
main
示例运行:
$ bash return_test.sh
hello
$ source return_test.sh
$ main
hello
如果脚本来源,return
将返回父(当然),但如果脚本执行,return
将产生错误,脚本将继续执行。
我在GNU Bash 4.2,4.3和4.4
上测试了这个这是基于mr.spuratic's answer上How to detect if a script is being sourced的部分内容。
请注意,此方法适用于Bash,但不适用于大多数其他shell。
答案 4 :(得分:1)
我一直在我所有脚本的底部使用以下构造:
[[ "$(caller)" != "0 "* ]] || main "$@"
脚本中的其他所有内容都在函数中定义,或者是全局变量。
caller
被记录为“返回当前子例程调用的上下文”。当源脚本被来源时,调用者的结果从源于此脚本的脚本的行号开始。如果未提供此脚本,则以"0 "
我使用!=
和||
代替=
和&&
的原因是后者会导致脚本在源文件时返回false。如果外部脚本在set -e
下运行,则可能导致外部脚本退出。
请注意,我只知道这适用于bash。它不适用于posix shell。我不知道其他shell如ksh或zsh。